1、執行緒生命週期
執行緒總共有5大狀態
-
新建狀態:新建執行緒物件,並沒有呼叫start()方法之前
-
就緒狀態:呼叫start()方法之後執行緒就進入就緒狀態,但是並不是說只要呼叫start()方法執行緒就馬上變為當前執行緒,在變為當前執行緒之前都是為就緒狀態。值得一提的是,執行緒在睡眠和掛起中恢復的時候也會進入就緒狀態哦。
-
執行狀態:執行緒被設定為當前執行緒,開始執行run()方法。就是執行緒進入執行狀態
-
阻塞狀態:執行緒被暫停,比如說呼叫sleep()方法後執行緒就進入阻塞狀態
-
死亡狀態:執行緒執行結束
鎖型別
-
lock():獲取鎖,如果鎖被暫用則一直等待
-
unlock():釋放鎖
-
tryLock(): 注意返回型別是boolean,如果獲取鎖的時候鎖被佔用就返回false,否則返回true
-
tryLock(long time, TimeUnit unit):比起tryLock()就是給了一個時間期限,保證等待引數時間
-
lockInterruptibly():用該鎖的獲得方式,如果執行緒在獲取鎖的階段進入了等待,那麼可以中斷此執行緒,先去做別的事
package cn.xiang.thread.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * lock鎖學習demo * 總結: * 1、使用lock.lock()方法可以將物件鎖定。同時必須在finally將鎖釋放lock.unlock(),否則其他物件獲取不了該鎖。 * 2、如果是執行緒內新定義的物件,那麼有無鎖都會非同步執行,並不同步。 * @author 向寧 *日期:2018年4月11日 *時間:下午3:26:06 * */ public class LockDemo01 { /** * 建立鎖 */ private Lock lock = new ReentrantLock(); /** * 需要同步執行的方法 * @param thread * @throws InterruptedException */ public void lockMethod(){ System.out.println("還沒開始鎖定"); lock.lock(); Thread thread = Thread.currentThread(); System.out.println("我是" + thread.getName() + "!正在使用鎖"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public static void main(String[] args) { final LockDemo01 lockDemo = new LockDemo01(); Thread t1 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t2 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; t1.start(); t2.start(); } }
結果如下:
package cn.xiang.thread.lock; /** * lock.tryLock() * 可if判斷該程式碼是否被鎖定。如果被鎖定,則不執行。 * lock.tryLock(time, unit) * 給一個等待時間,等待時間過後,如果鎖定被釋放,則可以直接進入。如果等待時間已過,還不釋放。則直接執行else * */ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockDemo02 { private Lock lock = new ReentrantLock(); /** * 需要同步的方法 */ public void lockMethod(){ try { System.out.println("開始執行方法"); if (lock.tryLock(1, TimeUnit.SECONDS)) { //如果當前已經被鎖定 try { System.out.println("我是執行緒:" + Thread.currentThread().getName() + "!我已經拿到了該鎖!"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } }else{ System.out.println("我是執行緒:" + Thread.currentThread().getName() + "!我沒有拿到該鎖,就不要了!"); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { final LockDemo02 lockDemo = new LockDemo02(); Thread t1 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t2 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; Thread t3 = new Thread(){ @Override public void run(){ lockDemo.lockMethod(); } }; t1.start(); t2.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t3.start(); } }
結果如下:
以下是一個簡單的死鎖
package cn.xiang.thread; public class ThreadDeadLock03 { public static void main(String[] args) { LockDemo04 lock = new LockDemo04(false); new Thread(lock).start(); new Thread(lock).start(); } } class LockDemo04 implements Runnable{ private boolean flag; private Object obj1 = new Object(); private Object obj2 = new Object(); public LockDemo04(boolean flag){ this.flag = flag; } @Override public void run() { flag = !flag; try { if(flag){ synchronized(obj1){ System.out.println("已經拿到obj1的物件鎖"); Thread.sleep(1000); System.out.println("準備拿obj2的物件鎖"); synchronized(obj2){ System.out.println("已經拿到obj2的物件鎖,表示沒有發生死鎖"); } } }else{ synchronized(obj2){ System.out.println("已經拿到obj2的物件鎖"); Thread.sleep(1000); System.out.println("準備拿obj1的物件鎖"); synchronized(obj1){ System.out.println("已經拿到obj1的物件鎖,表示沒有發生死鎖!"); } } } } catch (Exception e) { // TODO: handle exception } } }
效果: