進程是執行者的應用程序,而線程是進程內部的一個執行序列.一個進程可以有多個線程.線程又叫輕量級進程.
創建線程的三種方式:
I> 繼承Thread類
II> 實現Runnable接口
III> 應用程序可以使用Executor框架來創建線程池
實現Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類.在用用設計中已經繼承類別的對象的情況下,這需要多繼承(而Java不支持多繼承),只能實現接口.同時,線程池也是非常高效的,很容易實現和使用.
線程的狀態:
I> 新建(new):新創建了一個對象.
II> 可運行(runnable):線程新創建對象後,其他線程(比如main線程)調用了該對象的start()方法,該狀態的線程位於可運行的線程池中,等待被線程調度選中,獲取CPU的使用權.
III> 運行(running):可運行狀態的線程獲得了CPU的時間片,執行代碼.
IV> 阻塞(block):阻塞狀態是指線程因為某種原因放棄了CPU的使用權,也即讓出了CPU時間片,暫時停止運行.直到線程進入可運行狀態,才有機會再次獲得CPU時間片轉到運行狀態.
阻塞的情況分為3種:
a> 等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待隊列中.
b> 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中.
c> 其他阻塞:運行的線程執行Thread.sleep(long ms)或t.join()方法,或者發出了I/O請求,JVM會把該線程置為阻塞狀態.當sleep()狀態超時時,join()等待線程終止或超時或I/O處理完畢,線程重新轉入可運行狀態.
V> 死亡(dead):線程run(),main()方法執行結束,或者因異常退出run()方法,則該線程結束生命周期,死亡的線程不可再次復生.
同步方法默認用this或者當前類class對象作為鎖.
同步代碼塊可以選擇以什麼來加鎖,比同步方法要更加細顆粒度,我們可以選擇只同步會發生同步問題的部分代碼而不是整個方法.
使用多個線程的時候,一種非常簡單的避免死鎖的方式就是:指定獲取死鎖的順序,並強制按照指定的順序獲取鎖.因此如果所有的線程都是一同樣的順序加鎖和釋放鎖,就不會出現死鎖了.