《Java 高并发》03 线程的生命周期
相關概念
進程是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啟動多個線程。
一個進程是一個獨立的運行環境,它可以被看作一個程序或者一個應用。而線程是在進程中執行的一個任務。Java運行環境是一個包含了不同的類和程序的單一進程。線程可以被稱為輕量級進程。線程需要較少的資源來創建和駐留在進程中,并且可以共享進程中的資源。
多線程程序中,多個線程被并發的執行以提高程序的效率,CPU不會因為某個線程需要等待資源而進入空閑狀態。多個線程共享堆內存(heap memory),因此創建多個線程去執行一些任務會比創建多個進程更好。舉個例子,Servlets 比 CGI 更好,是因為 Servlets 支持多線程而 CGI 不支持。
這里所謂的多個線程“同時”執行是人的感覺,實際上,是多個線程輪換執行。
線程調度器(Thread Scheduler)是一個操作系統服務,它負責為Runnable狀態的線程分配CPU時間。一旦我們創建一個線程并啟動它,它的執行便依賴于線程調度器的實現。
時間片(Time Slicing)是指將可用的CPU時間分配給可用的Runnable線程的過程。分配CPU時間可以基于線程優先級或者線程等待的時間。線程調度并不受到Java虛擬機控制,所以由應用程序來控制它是更好的選擇(也就是說不要讓你的程序依賴于線程的優先級)。
線程的生命周期(六種狀態)
public enum State {NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED; }- NEW:只存在于線程剛創建,未調用start之前。
- RUNNABLE:正在 JVM 中執行,但是這個"執行",不一定是真的在運行, 也有可能是在等待CPU資源。所以,在網上,有人把這個狀態區分為READY和RUNNING兩個,一個表示的start了,資源一到位隨時可以執行,另一個表示真正的執行中,這取決于操作系統處理器。
- BLOCKED:線程等待獲取一個鎖,來繼續執行下一步的操作,比較經典的就是synchronized關鍵字,這個關鍵字修飾的代碼塊或者方法,均需要獲取到對應的鎖,在未獲取之前,其線程的狀態就一直未BLOCKED,如果線程長時間處于這種狀態下,我們就要當心是否會出現死鎖的情況。
-
WAITING:等待狀態。進入這個狀態,一定是執行了如下的一些代碼,例如
- Object.wait()
- Thread.join()
- LockSupport.park()
當一個線程執行了Object.wait()的時候,它一定在等待另一個線程執行Object.notify()或者Object.notifyAll()。或者一個線程thread,其在主線程中被執行了thread.join()的時候,主線程即會等待該線程執行完成。當一個線程執行了LockSupport.park()的時候,其在等待執行LockSupport.unpark(thread)。當該線程處于這種等待的時候,其狀態即為WAITING。需要關注的是,這邊的等待是沒有時間限制的,當發現有這種狀態的線程的時候,若其長時間處于這種狀態,也需要關注下程序內部有無邏輯異常。
LockSupport.park()
public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState());LockSupport.unpark(thread1);Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {LockSupport.park();} }Object.wait()
public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread thread1 = new MyThread(lock);thread1.start();Thread.sleep(100);System.out.println(thread1.getState()); //這時候線程狀態應為WAITINGsynchronized (lock){lock.notify(); //notify通知wait的線程}Thread.sleep(100);System.out.println(thread1.getState());}}class MyThread extends Thread {private byte[] lock = new byte[0];public MyThread(byte[] lock) {this.lock = lock;}@Overridepublic void run() {synchronized (lock){try {lock.wait(); //wait并允許其他線程同步lock} catch (InterruptedException e) {e.printStackTrace();}}} }Thread.join()
public class MyThreadTest {public static void main(String[] args) throws InterruptedException {byte[] lock = new byte[0];MyThread1 thread1 = new MyThread1(lock);thread1.start();MyThread2 thread2 = new MyThread2(thread1);thread2.start();Thread.sleep(100);System.out.println(thread2.getState());}}class MyThread1 extends Thread {private byte[] lock = new byte[0];public MyThread1(byte[] lock) {this.lock = lock;}@Overridepublic void run() {try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}} }class MyThread2 extends Thread {Thread thread;public MyThread2(Thread thread) {this.thread = thread;}@Overridepublic void run() {try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}} } -
TIMED_WAITING:這個狀態和WAITING狀態的區別就是,這個狀態的等待是有一定時效的,即可以理解為WAITING狀態等待的時間是永久的,即必須等到某個條件符合才能繼續往下走,否則線程不會被喚醒。但是TIMED_WAITING,等待一段時間之后,會喚醒線程去重新獲取鎖。當執行如下代碼的時候,對應的線程會進入到TIMED_WAITING狀態。
- Thread.sleep(long)
- Object.wait(long)
- Thread.join(long)
- LockSupport.parkNanos()
- LockSupport.parkUntil()
-
TERMINATED:這個狀態很好理解,即為線程執行結束之后的狀態
線程的狀態圖
?
總結
以上是生活随笔為你收集整理的《Java 高并发》03 线程的生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(497):布局之居中布局
- 下一篇: Could not autowire.