Java執行緒生命週期和鎖的簡單使用
本文介紹了java執行緒的生命週期,Synchronized的幾個方法簡單的使用。
執行緒生命週期
-
初始狀態(New)
New Thread之後,
-
就緒狀態(Ready)
表示獲取到了Cpu的執行時間片,也就是cpu的執行權,等待開始執行。
-
執行狀態(Runable)
執行start之後,開始執行。
-
阻塞狀態(Blocked)
在進入synchronized的臨界區或者Lock的臨界區,等待獲取監視器(monitor)鎖,執行緒會進入同步佇列(SynchronizedQueue)中。
-
等待狀態:(Waiting)
在執行await(),wait(),jion(),LockSupport.park()方法進入等待狀態;
-
等待超時狀態
在執行Object.await(time),Object.wait(time),Object.sellp(time),LockSupport.parkUntil,lockSupport.parkNanos 進入等待超時狀態。
-
終止狀態
執行緒執行完畢或者執行了Thread.interrupt() / Thread.stop(),不建議使用的Thread.stop() 因為 Thread.stop是直接強行結束,不會釋放資源 ;
-
配圖
鎖的幾個簡單方法
-
wait 和 notify/notifyAll
解釋
wait: 將執行緒狀態置位 '等待狀態',進入等待佇列等待。 notify/notifyAll:
**提示:**wait,notify/notifyAll都需要在獲取到監視器所(monitor)後才可以進行操作。
程式碼
public class WaitAndNotifyTest { private static Object obj = new Object(); public static void main(String[] args) { // 建立執行緒 thread1 Thread thread1 = new
執行結果: thread2 begin wait... thread1 begin wait... thread1 end wait... thread2 end wait... 複製程式碼
-
await,signal/signalAll
解釋
await,signal/signalAll方法是Lock Condition的方法,語義和Object的wait,notify/notifyAll是完全相同的。
程式碼
/** * @Auther: lantao * @Date: 2019-04-15 14:49 * @Company: * @maill: * @Description: Condition 條件 有 singal signalAll 和 await 方法 和Object 的 notify notifyAll 和 wait 是一個意思同樣會釋放鎖 執行singal和notify的時候也需要在等待獲取鎖 */ public class LockCondition { public static ReentrantLock lock = new ReentrantLock(); public static Condition a = lock.newCondition(); public static void main(String[] args) throws InterruptedException { Runnable runnable = () -> { try { lock.lock(); System.out.println(Thread.currentThread().getName()); System.out.println("1"); a.await(); System.out.println(Thread.currentThread().getName() + "被喚醒了"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } }; Runnable runnable1 = () -> { try { lock.lock(); System.out.println("執行緒" +Thread.currentThread().getName() + "開始執行sinal"); a.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } }; new Thread(runnable,"Thread1").start(); new Thread(runnable,"Thread2").start(); Thread.sleep(100); new Thread(runnable1,"Thread3").start(); } } 複製程式碼
執行結果: Thread1 Thread2 執行緒Thread3開始執行sinal Thread1被喚醒了 Thread2被喚醒了 複製程式碼
-
Join 和 Join(time)
解釋
等待呼叫Join的執行緒執行完成後再繼續執行,或者等待時間超過了超時時間繼續執行;
程式碼
/** * @Auther: lantao * @Date: * @Company: * @maill: * @Description: Join 核心是等待指定執行緒執行完後再繼續執行 Join(time) 就是等待執行緒執行的一個超時時間 超過了就繼續執行了 */ public class JoinTest { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new Runnable() { @Override public void run() { System.out.println("1"); try { Thread.sleep(2000L); System.out.println("正常完成"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("2"); } }); thread1.start(); // 執行 jion 等待執行緒 thread1 執行完後再繼續執行 thread1.join(); // thread1.join(1000); // 這樣最終執行的順序是 1 2 3 如果不增加 thread1.join() 結果可能是 312 也可能是 132 // Join 核心是等待指定執行緒執行完後再繼續執行 System.out.println("3"); } } 複製程式碼
執行結果: 1 正常完成 2 3 複製程式碼
-
yield
解釋
yeid 方法的核心是讓出 cpu 時間片 ,也就是cpu執行權,執行緒會直接進入就緒狀態,執行緒排程器會從執行緒就緒佇列裡獲取一個執行緒優先順序最高的執行緒來執行,當然也有可能直接會去到剛剛讓出cpu執行權的執行緒,繼續執行yield 後續的程式碼。
程式碼
/** * @Auther: lantao * @Date: 2019-03-25 17:20 * @Company: * @maill: * @Description: */ public class YieldTest { private static Object obj = new Object(); public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 開始執行 yield "); Thread.yield(); System.out.println("trhead1"); } } } },"thread1"); Thread thread2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 開始執行 yield "); Thread.yield(); System.out.println("trhead2"); } } } },"thread2"); Thread thread3 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 開始執行 yield "); Thread.yield(); System.out.println("trhead3"); } } } },"thread3"); // 執行三個執行緒, 正常當執行到yield 是 就會讓出cpu執行權,執行緒到 就緒狀態,執行緒排程器會從 執行緒就緒佇列裡獲取一個執行緒優先順序最高的執行緒來執行, // 當然也有可能直接會去到剛剛讓出cpu的執行緒,繼續執行yield 後續的程式碼 thread1.start(); thread3.start(); thread2.start(); } } 複製程式碼
執行結果: thread1 開始執行 yield thread2 開始執行 yield thread3 開始執行 yield trhead2 trhead1 trhead3 複製程式碼
-
interrupt 和 stop
解釋
interrupt和stop都代表中斷執行緒,區別是 interrupt 會釋放資源而stop不會,interrupt也不會立馬就中斷;說道interrupt就得說一下isInterrupted方法,他是判斷執行緒中斷標誌的,如果執行緒A執行了執行緒B的interrupt方法,執行緒B在自己的執行緒中也可以使用 isInterrupted 方法判斷自己的中斷標誌。 注意:在使用 interrupt方法時,如果執行緒在sleep wait wait(time)狀態, 丟擲InterruptedException異常後會清除 isInterrupted 方法獲取的中斷標誌位,反之則不會
程式碼
/** * @Auther: lantao * @Date: 2019-04-17 17:18 * @Company: * @maill: * @Description: 在使用 interrupt方法是,如果執行緒咋sleep wait wait(time) 在丟擲InterruptedException異常後會 清除 isInterrupted 方法獲取的標誌位 其他則不會 */ public class InterruptTest { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { while (true) {} },"迴圈執行緒"); Thread thread2 = new Thread(() -> { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } },"睡眠執行緒"); Thread thread3 = new Thread(() -> { Object o = new Object(); while (true) { synchronized (o){ try { o.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } },"等待執行緒"); thread1.start(); thread2.start(); thread3.start(); Thread.sleep(500); thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); Thread.sleep(500); System.out.println("迴圈執行緒isInteryupt is " + thread1.isInterrupted()); System.out.println("睡眠執行緒isInteryupt is " + thread2.isInterrupted()); System.out.println("等待執行緒isInteryupt is " + thread3.isInterrupted()); } } 複製程式碼
執行結果: java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.com.concurrenncy.InterruptTest.lambda$main$1(InterruptTest.java:20) at java.lang.Thread.run(Thread.java:748) java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.com.concurrenncy.InterruptTest.lambda$main$2(InterruptTest.java:32) at java.lang.Thread.run(Thread.java:748) 迴圈執行緒isInteryupt is true 睡眠執行緒isInteryupt is false 等待執行緒isInteryupt is false 複製程式碼
部落格地址:lantaoblog.site