在Java併發編程中,線程所處的狀態以及創建線程的方式算是’開學第一課’了。而從本文開始,我將對Java併發做一個系統的認識。話不多說,開始進入主題。
一:線程狀態
在Thread類中詳細的枚舉了線程的狀態,如下:
public enum State {
/**
* 創建了線程還未調用srart()方法的時候,線程處於NEW的狀態
*/
NEW,
/**
* 線程處於可運行的狀態,在此狀態下,如果操作系統分配了相應的時間片
* 則線程將開始真正的運行
*/
RUNNABLE,
/**
* 線程處於阻塞狀態,在此狀態下將等待着直到獲得監視器鎖。
* 以下情況將進入阻塞狀態
* 一:進入同步被synchronized修飾的同步代碼塊,方法或者鎖的重入
*/
BLOCKED,
/**
* 線程出於等待的狀態,以下的方法將會使線程出於此狀態:
* 一:調用了object.wait()方法
* 二:調用了thread.join()方法
* 三:調用了LockSupport()方法
* 處於於此狀態的線程將等待着另一個線程執行特定的操作,比如調用了wait()方法
* 將等待着另一個線程調用notify()或者notifyAll 的方法喚醒。
*/
WAITING,
/**
* 超時等待的狀態.以下操作將進入超時等待的狀態:
* 一:Thread.sleep()方法的調用
* 二:object.wait(long) 加入超時時間的wait方法
* 三:thread.join(long millis)
* 四:LockSupport.parkNanos() 或者LockSupport..parkUntil()
*/
TIMED_WAITING,
/**
* 終止狀態的線程
* 線程完成了所有的操作處於此狀態
*/
TERMINATED;
}
以上的枚舉我們可以清楚的看到線程有NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED 6種狀態,線程總是處於6種狀態的某一種。我們將通過一個圖更加清楚的看看各個狀態之間是怎麼變更的:
上圖需要說明的是,在線程的枚舉狀態中,其實並沒有RUNING的狀態,RUNNABLE與RUNNING的狀態的區別是是否獲得了由操作系統分配的時間片,這裏爲了流程更加的清晰易懂,做了區分的處理。 以下,將從代碼的角度分析下線程的狀態:
public class ThreadState implements Runnable{
@Override
public void run() {
//RUNNABLE
System.out.println("線程的狀態爲:"+Thread.currentThread().getState());
}
public static void main(String[] args) {
Thread thread =new Thread(new ThreadState());
//NEW
System.out.println("線程的狀態爲:"+thread.getState());
thread.start();
}
}
才創建線程,線程處於NEW狀態,調用start方法後,獲得時間片後,執行run方法,線程處於RUNNABLE狀態。
public class ThreadState implements Runnable{
@Override
public void run() {
synchronized (ThreadState.class){
while (true){
System.out.println("線程的狀態爲:"+Thread.currentThread().getState());
}
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
Thread thread2 =new Thread(threadState);
thread1.start();
thread2.start();
}
}
查看線程的狀態,
可以看到先獲得時間片的線程處於RUNNABLE的狀態,而另外一個線程則處於BLOCK的狀態。
public class ThreadState implements Runnable{
@Override
public void run() {
synchronized (this){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
thread1.start();
}
}
當調用wait方法的時候,當前線程會處於WAITING狀態
public class ThreadState implements Runnable{
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ThreadState threadState = new ThreadState();
Thread thread1 =new Thread(threadState);
thread1.start();
}
}
當調用了sleep方法的時候,則線程處於TIMED_WAITING超時等待狀態。
二:創建線程的方式
這裏主要是對其進行一個總結:
1:實現Runnable接口或匿名內部類的方式
2:繼承Thread類
3:線程池的實現
4:帶返回值的線程創建方式(Callable與FutureTask)
5:Spring對異步的支持(@Async)
6:Lamada表達式中的並行計算