1. 程式人生 > >Lock介面與等待喚醒機制

Lock介面與等待喚醒機制

一  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();
    }
}

執行結果: