Lock介面與等待喚醒機制
阿新 • • 發佈:2019-01-10
一 Lock介面
Lock介面中常用的方法:
我們使用Lock介面,以及其中的lock()方法和unlock()方法替代同步,對電影院賣票案例中Ticket類進行如下程式碼修改:
package com.oracle.demo01; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Myticket4 implements Runnable { private int ticket=100; //建立Lock介面實現類物件private Lock lock=new ReentrantLock(); public void run() { while(true){ //獲取鎖 lock.lock(); if(ticket>0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"出售第"+ticket--+"張票"); } //釋放鎖 lock.unlock(); } } }
二 等待喚醒機制
在開始講解等待喚醒機制之前,有必要搞清一個概念——執行緒之間的通訊:多個執行緒在處理同一個資源,但是處理的動作(執行緒的任務)卻不相同。通過一定的手段使各個執行緒能有效的利用資源。而這種手段即—— 等待喚醒機制。
等待喚醒機制所涉及到的方法:
wait() :等待,將正在執行的執行緒釋放其執行資格 和 執行權,並存儲到執行緒池中。
notify():喚醒,喚醒執行緒池中被wait()的執行緒,一次喚醒一個,而且是任意的。
notifyAll(): 喚醒全部:可以將執行緒池中的所有wait() 執行緒都喚醒。
模擬資源類:
package com.oracle.demo03; public class Resource { //共享資源 public String name; public int age; //新增標記:true,賦值完成,false,輸出完成 public boolean flag=false;//先賦值在輸出 }
輸入執行緒類:
public class Input implements Runnable { //對Resource進行賦值 private Resource r; public Input(){} public Input(Resource r){ this.r=r; } public void run() { int i=0; while(true){ //新增同步程式碼塊 synchronized (r) { //判斷標記 if(r.flag){ try { r.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if(i%2==0){ r.name="張三"; r.age=18; }else{ r.name="李四"; r.age=81; } r.flag=true; r.notify(); } i++; } } }
輸出執行緒類:
public class Output implements Runnable { private Resource r; public Output(){} public Output(Resource r){ this.r=r; } public void run() { //對Resource進行輸出 while(true){ //新增同步鎖 synchronized (r) { //判斷標記 if(!r.flag){ try { r.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(r.name+"..."+r.age); //改標記,喚醒input r.flag=false; r.notify(); } } } }
測試類:
public class Demo01 { public static void main(String[] args) { Resource r=new Resource(); //建立執行緒任務 Input in=new Input(r); Output out=new Output(r); Thread tin=new Thread(in); Thread tout=new Thread(out); tin.start(); tout.start(); } }
執行結果: