java多線程(3)生產者消費者問題(二)

一、疑問

如果我們想執行具體喚醒哪個阻塞的線程,應該怎麼做?

在之前解決線程安全的過程中,雖然我們可以理解同步代碼塊和同步方法的鎖對象問題,
但是我們並沒有直接看到在哪裏加上了鎖,在哪裏釋放了鎖,
爲了①更清晰的表達如何加鎖和釋放鎖 ②指定具體喚醒哪個線程
JDK5以後提供了一個新的鎖對象Lock。

使用Lock改寫生產者消費者問題(只改動了Resource類):

package com.thread.pcprob2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 共享數據
 * @author dqf
 *
 */
public class Resource {
       //產品編號
       private Integer proNo = 0;
       //判斷是消費數據,還是生產數據
       private boolean flag = false;

       Lock lock = new ReentrantLock();

       //生產者阻塞
       Condition condition1 = lock.newCondition();
       //消費者阻塞
       Condition condition2 = lock.newCondition();

       //生產數據
       public void produce(){

             lock.lock();
             try {
                    while(flag){//如果flag=true,則等待消費;
                          condition1.await();
                    }
                    System.out.println("生產-->" + (++proNo));
                    flag = true;
                    condition2.signal();
             } catch (Exception e) {

             }finally{
                    lock.unlock();
             }
       }

       //消費數據
       public void consume(){
             lock.lock();
             try {
                    while(!flag){//如果flag=false,則等待生產
                          condition2.await();
                    }
                    System.out.println("消費-------->" + proNo);
                    flag = false;
                    condition1.signal();
             } catch (Exception e) {
                    // TODO: handle exception
             }finally{
                    lock.unlock();
             }

       }
}
package com.thread.pcprob2;

/**
 * 消費者
 * @author dqf
 *
 */
public class Consumer implements Runnable{

       private Resource res;

       public Consumer(Resource res) {
             this.res = res;
       }

       @Override
       public void run() {
             while(true){
                    res.consume();
             }
       }
}
package com.thread.pcprob2;

/**
 * 生產者
 * @author dqf
 *
 */
public class Producer implements Runnable{

       private Resource res;

       public Producer(Resource res) {
             this.res = res;
       }

       @Override
       public void run() {
             while(true){
                    res.produce();
             }
       }
}
package com.thread.pcprob2;

public class App {
       public static void main(String[] args) {
             Resource res = new Resource();

             Producer p = new Producer(res);
             Consumer c = new Consumer(res);

             Thread t1 = new Thread(p);
             Thread t2 = new Thread(p);

             Thread t3 = new Thread(c);
             Thread t4 = new Thread(c);

             t1.start();
             t2.start();
             t3.start();
             t4.start();

       }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章