Java提升——多線程(一)狀態圖

操做系統中的進程和線程的概念
       進程是指一個內存運行的應用程序,每一個進程都有本身獨立的一塊內存空間,一個進程中能夠啓動多個線程,好比windows下的一個運行的應用程序.exe就是一個進程。
       線程是指進程中的一個執行流,一個進程能夠運行多個線程。如java.exe就能夠運行不少個線程。線程老是屬於某個進程,進程中的多個線程共享進程中的內存。
       操做系統中能夠同時執行多個任務,每一個任務就是進程;進程能夠同時執行多個任務,每一個任務就是線程。
   
線程的狀態


一、新建(new):線程對象被建立後就進入了新建狀態。如:Thread thread = new Thread();java

二、就緒狀態(Runnable):也被稱爲「可執行狀態」。線程對象被建立後,其餘線程調用了該對象的start()方法,從而啓動該線程。如:thread.start(); 處於就緒狀態的線程隨時可能被CPU調度執行。windows

三、運行狀態(Running):線程獲取CPU權限進行執行。須要注意的是,線程只能從就緒狀態進入到運行狀態。多線程

四、阻塞狀態(Blocked):阻塞狀態是線程由於某種緣由放棄CPU使用權限,暫時中止運行。直到線程進入就緒狀態,纔有機會進入運行狀態。阻塞的三種狀況:ide

    1)等待阻塞:經過調用線程的wait()方法,讓線程等待某工做的完成。this

    2)同步阻塞:線程在獲取synchronized同步鎖失敗(由於鎖被其餘線程佔用),它會進入同步阻塞狀態。spa

    3)其餘阻塞:經過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或超時、或者I/O處理完畢時,線程從新轉入就緒狀態。
操作系統

五、死亡狀態(Dead):線程執行完了或因異常退出了run()方法,該線程結束生命週期。線程

經常使用的實現多線程的方式

一、繼承Thread類3d

public class Thread implements Runnable {、、、、、}

由Thread的源碼能夠看出,Thread是實現了Runnable接口。code

二、實現Runnable接口

public interface Runnable {
     public abstract void run(); }

Runnable接口只有一個run()方法

————————————————————————————————————————————————

Thread和Runnable都是是實現實現多線程的方式。不一樣的是Thread是類,Runnable是接口——Thread自己實現了Runnable接口,一個類只能有一個父類,可是卻能夠是實現多個接口,所以Runnable具備更好的擴展性

Thread實現多線程

public class MyThread extends Thread {
    private int i ;  @Override/** 重寫run方法*/  public void run(){
        for (int i = 0; i < 50 ; i++) {
            /**  * 當繼承Thread類能夠直接用this獲取當前線程  * 用getName()獲取當前線程的名字  */  System.out.println(this.getName()+"-"+i);  }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100 ; i++) {
            //經過Thread.currentThread()獲取當前線程  System.out.println(Thread.currentThread().getName()+" "+i);  if(i==20){
                //建立並啓動第一個線程  new MyThread().start();  //建立並啓動第二個線程  new MyThread().start();  }
        }
    }
}

Runnable實現多線程

public class MyRunnable implements Runnable {
    private int i;   @Override  public void run() {
        for (int i = 0; i < 50; i++) {
            /**當線程類實現Runnable接口的時候,獲取當前線程只能用Thread.currentThread()*/  System.out.println(Thread.currentThread().getName()+" "+i);  }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
           // System.out.println(Thread.currentThread().getName()+" "+i);  if(i==20){
                MyRunnable mr = new MyRunnable();  //經過new Start()方法建立新線程  new Thread(mr,"線程1").start();  new Thread(mr,"線程2").start();  }

        }
    }
}
關於線程中的start()和run()

啓動線程使用start(),而不是run()!


在執行start()方法以前,只是有一個Thread對象,還沒一個真正的線程。(分配內存,初始化成員變量

——>start()以後,線程狀態重新狀態到可執行狀態。(調用棧和計數器,線程沒運行,只是能夠運行

——>當線程得到執行機會時,其目標run()方法將運行。

start():他的做用是啓動一個新線程,新線程會調用相應的run()方法。start()不能被重複調用。

run():和普通成員的方法同樣能夠被重複調用。單獨調用run()會在當前線程中執行run(),而不會啓動新的線程。

public class MyThread extends Thread {  @Override/** 重寫run方法*/  public void run(){
       
        }
    }
MyThread myThread = new MyThread();

如:myThread.start()會啓動一個新的線程,而後在新線程中執行run()方法。

myThread.run()會直接在當前線程中運行run()方法,不會啓動一個線程。

start方法源碼:

public synchronized void start() {
     /**     *若是線程不是就緒狀態就拋出異常     */  if (threadStatus != 0)
         throw new IllegalThreadStateException();   /* 將線程添加到group當中 */  group.add(this);   boolean started = false;  try {
         start0();//經過start0啓動線程  started = true;//設置started標記  } finally {
         try {
             if (!started) {
                 group.threadStartFailed(this);  }
         } catch (Throwable ignore) {
             /* do nothing. If start0 threw a Throwable then  it will be passed up the call stack */  }
     }
 }

run方法源碼:

public void run() {
    if (target != null) {
        target.run();  }
}

其中target是Runnable對象, 直接調用Thread線程中Runnable接口中run方法,不會新建一個線程。

當線程得到CPU,開始執行run()方法的線程執行體,則該線程處於運行狀態。

關於阻塞


進入阻塞的狀況:   解除上面阻塞狀況:

一、線程調用sleep()方法主動釋放佔用的處理器資源

二、調用了一個阻塞式的IO方法,在方法返回前線程被阻塞

三、線程得到了一個同步監視器(Syschronized),但該監視器正被其餘線程持有

四、線程在等待某個通知(notify)

五、程序調用了線程的resume()方法將線程掛起。可是該方法容易發生死鎖,因此儘可能避免使用

 

一、調用sleep()方法通過了指定的時間

二、線程調用的IO阻塞方法已經返回

三、線程成功的得到了試圖取得的同步監視器

四、線程正在等待某個通知時,其餘線程發出了一個通知

五、處於掛起的線程被調用了resume()恢復方法。

線程從阻塞狀態只能進入就緒狀態,沒法進入運行狀態,而從就緒到運行不受程序控制,由系統線程調度決定。

得到資源進入運行狀態,失去資源進入就緒狀態。

線程死亡


線程死亡會以一下三種情況結束:

—>調用run或call方法執行完成,正常結束

—>線程拋出一個爲捕獲的Exception或Error

—>直接調用stop()方法來結束該線程——容易致使死鎖,不推薦


不要試圖對死亡的線程使用start()方法,將會拋出異常,並不會重啓死亡的異常!

相關文章
相關標籤/搜索