文章出處

線程狀態

新建狀態

線程被創建時,會短暫的處于這種狀態。處于這種狀態的線程已經分配了必須的系統資源,有資格獲得cpu時間了,等待調度器把它轉變為可運行狀態或阻塞狀態;

就緒狀態

在這種狀態下,只要調度器把時間片分配給線程,就可以馬上運行;

阻塞狀態

線程因為某個條件未滿足,阻止了它的運行;這種狀態會被調度器忽略,直到條件滿足時,轉為就緒狀態;

死亡狀態

線程運行結束或被中斷后的狀態;該狀態不能被調度,不會分配cpu時間;

線程進入阻塞狀態的方式

  • 調用sleep方法
  • 調用wait方法
  • 任務等待某個輸入輸出完成
  • 調用其它同步控制方法,等待其它線程釋放鎖

線程中斷

線程阻塞及中斷

先看一段代碼,如下:

package concurrency;

import java.util.concurrent.*;
import java.io.*;

class SleepBlocked implements Runnable {
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("InterruptedException");
        }
        System.out.println("Exiting SleepBlocked.run()");
    }
}

class IOBlocked implements Runnable {
    private InputStream in;

    public IOBlocked(InputStream is) {
        in = is;
    }

    public void run() {
        try {
            System.out.println("Waiting for read():");
            in.read();
        } catch (IOException e) {
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Interrupted from blocked I/O");
            } else {
                throw new RuntimeException(e);
            }
        }
        System.out.println("Exiting IOBlocked.run()");
    }
}

class SynchronizedBlocked implements Runnable {
    public synchronized void f() {
        while (true) // Never releases lock
            Thread.yield();
    }

    public SynchronizedBlocked() {
        new Thread() {
            public void run() {
                f(); // Lock acquired by this thread
            }
        }.start();
    }

    public void run() {
        System.out.println("Trying to call f()");
        f();
        System.out.println("Exiting SynchronizedBlocked.run()");
    }
}

public class Interrupting {
    private static ExecutorService exec = Executors.newCachedThreadPool();

    static void test(Runnable r) throws InterruptedException {
        Future<?> f = exec.submit(r);
        TimeUnit.MILLISECONDS.sleep(100);
        System.out.println("Interrupting " + r.getClass().getName());
        f.cancel(true); // Interrupts if running
        System.out.println("Interrupt sent to " + r.getClass().getName());
    }

    public static void main(String[] args) throws Exception {
        test(new SleepBlocked());
        test(new IOBlocked(System.in));
        test(new SynchronizedBlocked());
        TimeUnit.SECONDS.sleep(3);
        System.out.println("Aborting with System.exit(0)");
        System.exit(0); // ... since last 2 interrupts failed
    }
} 
View Code

以上代碼中,展示了三種進入阻塞狀態的情景:調用sleep方法,等待io,等待其它線程釋放鎖;

以及嘗試調用Future的cancel方法去中斷阻塞的線程,從運行結果可以發現,只有sleep可以被中斷,其它等待io和等待鎖釋放都不能被中斷;這一點也可以從sleep方法會拋出InterruptedException異常看出來,其它兩個不會拋出該異常;

那么對于io阻塞和互斥鎖阻塞的線程如何中斷?

中斷io阻塞

方式一,調用shutdownNow關閉線程池,調用close方法關閉IO流資源;

方式二,使用nio

中斷互斥鎖阻塞

使用并發庫中的ReentrantLock鎖;

ps:如果是同一個線程的話,是可以調用在同一個對象中的其它synchronized方法;

檢查中斷

調用Thread.interrupted(),查看interrupt()是否調用過,并清除中斷狀態,避免中斷被通知兩次;

 


文章列表


不含病毒。www.avast.com
全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()