基礎知識點:
JDK 中用Thread.State 類定義了線程的幾種狀態
要想實現多線程,必須在主線程中創建新的線程對象。Java語言使用Thread類
及其子類的對象來表示線程,在它的一個完整的生命周期中通常要經歷如下的 五
種狀態:
新建: 當一個Thread類或其子類的對象被聲明並創建時,新生的線程對象處於新建
狀態
就緒:處於新建狀態的線程被start()后,將進入線程隊列等待CPU時間片,此時它已
具備了運行的條件,只是沒分配到CPU資源
運行:當就緒的線程被調度並獲得CPU資源時,便進入運行狀態, run()方法定義了線
程的操作和功能
阻塞:在某種特殊情況下,被人為掛起或執行輸入輸出操作時,讓出 CPU 並臨時中
止自己的執行,進入阻塞狀態
死亡:線程完成了它的全部工作或線程被提前強制性地中止或出現異常導致結束
解決方法:
/**
* 例子:創建三個窗口賣票,總票數為100張.使用實現Runnable接口的方式
*
* 1.問題:賣票過程中,出現了重票、錯票 -->出現了線程的安全問題
* 2.問題出現的原因:當某個線程操作車票的過程中,尚未操作完成時,其他線程參與進來,也操作車票。
* 3.如何解決:當一個線程a在操作ticket的時候,其他線程不能參與進來。直到線程a操作完ticket時,其他
* 線程才可以開始操作ticket。這種情況即使線程a出現了阻塞,也不能被改變。
*
*
* 4.在Java中,我們通過同步機制,來解決線程的安全問題。
*
* 方式一:同步代碼塊
*
* synchronized(同步監視器){
* //需要被同步的代碼
*
* }
* 說明:1.操作共享數據的代碼,即為需要被同步的代碼。 -->不能包含代碼多了,也不能包含代碼少了。
* 2.共享數據:多個線程共同操作的變量。比如:ticket就是共享數據。
* 3.同步監視器,俗稱:鎖。任何一個類的對象,都可以充當鎖。
* 要求:多個線程必須要共用同一把鎖。
*
* 補充:在實現Runnable接口創建多線程的方式中,我們可以考慮使用this充當同步監視器。
* 方式二:同步方法。
* 如果操作共享數據的代碼完整的聲明在一個方法中,我們不妨將此方法聲明同步的。
*
*
* 5.同步的方式,解決了線程的安全問題。---好處
* 操作同步代碼時,只能有一個線程參與,其他線程等待。相當於是一個單線程的過程,效率低。 ---局限性
*
* @author ch
* @create 2019-02-13 下午 4:47
*/
class Window1 implements Runnable{ private int ticket = 100; // Object obj = new Object(); // Dog dog = new Dog(); @Override public void run() { // Object obj = new Object(); while(true){ synchronized (this){//此時的this:唯一的Window1的對象 //方式二:synchronized (dog) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":賣票,票號為:" + ticket); ticket--; } else { break; } } } } } public class WindowTest1 { public static void main(String[] args) { Window1 w = new Window1(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); } }