当前位置:天才代写 > tutorial > JAVA 教程 > Java多线程:“基本篇”11之出产消费者问题

Java多线程:“基本篇”11之出产消费者问题

2017-11-02 08:00 星期四 所属: JAVA 教程 浏览:82

副标题#e#

1. 出产/消费者模子

出产/消费者问题是个很是典范的多线程问题,涉及到的工具包罗“出产者”、“消 费者”、“客栈”和“产物”。他们之间的干系如下:

(01) 出产者仅仅在仓储未满时候出产,仓满则遏制出产。

(02) 消费者仅仅在仓储有产物时候才气消费,仓空则期待。

(03) 当消费者发明仓储没产物可消费时候会通知出产者出产。

(04) 出产者在出产出可消费产物时候,应该通知期待的消费者去消费。

2. 出产/消费者实现

下面通过wait()/notify()方法实现该模子(后头在进修了线程池相关内容之后,再通过其它方法实现 出产/消费者模子)。源码如下:

// Demo1.java
// 客栈
class Depot {
    private int capacity;    // 客栈的容量
    private int size;        // 客栈的实际数量
    
    public Depot(int capacity) {
        this.capacity = capacity;
        this.size = 0;
    }
    
    public synchronized void produce(int val) {
        try {
             // left 暗示“想要出产的数量”(有大概出产量太多,需多此出产)
            int left = val;
            while (left > 0) {
                // 库存已满时,期待“消费者”消费产物。
                while (size >= capacity)
                    wait();
                // 获取“实际出产的数量”(即库存中新增的数量)
                // 假如“库存”+“想要出产的数量”>“总的容量”,则“实际增量”=“总的容量”-“当前容量”。(此时填满客栈)
                // 不然“实际增量”=“想要出产的数量”
                int inc = (size+left)>capacity ? (capacity-size) : left;
                size += inc;
                left -= inc;
                System.out.printf("%s produce(%3d) --> left=%3d, inc=%3d, size=%3d\n", 
                        Thread.currentThread().getName(), val, left, inc, size);
                // 通知“消费者”可以消费了。
                notifyAll();
            }
        } catch (InterruptedException e) {
        }
    } 
    
    public synchronized void consume(int val) {
        try {
            // left 暗示“客户要消费数量”(有大概消费量太大,库存不足,需多此消费)
            int left = val;
            while (left > 0) {
                // 库存为0时,期待“出产者”出产产物。
                while (size <= 0)
                    wait();
                // 获取“实际消费的数量”(即库存中实际淘汰的数量)
                // 假如“库存”<“客户要消费的数量”,则“实际消费量”=“库存”;
                // 不然,“实际消费量”=“客户要消费的数量”。
                int dec = (size<left) ? size : left;
                size -= dec;
                left -= dec;
                System.out.printf("%s consume(%3d) <-- left=%3d, dec=%3d, size=%3d\n", 
                        Thread.currentThread().getName(), val, left, dec, size);
                notifyAll();
            }
        } catch (InterruptedException e) {
        }
    }
    
    public String toString() {
        return "capacity:"+capacity+", actual size:"+size;
    }
} 
    
// 出产者
class Producer {
    private Depot depot;
        
    public Producer(Depot depot) {
        this.depot = depot;
    }
    
    // 消费产物:新建一个线程向客栈中出产产物。
    public void produce(final int val) {
        new Thread() {
            public void run() {
                depot.produce(val);
            }
        }.start();
    }
}
    
// 消费者
class Customer {
    private Depot depot;
        
    public Customer(Depot depot) {
        this.depot = depot;
    }
    
    // 消费产物:新建一个线程从客栈中消费产物。
    public void consume(final int val) {
        new Thread() {
            public void run() {
                depot.consume(val);
            }
        }.start();
    }
}
    
public class Demo1 {  
    public static void main(String[] args) {  
        Depot mDepot = new Depot(100);
        Producer mPro = new Producer(mDepot);
        Customer mCus = new Customer(mDepot);
    
        mPro.produce(60);
        mPro.produce(120);
        mCus.consume(90);
        mCus.consume(150);
        mPro.produce(110);
    }
}


#p#副标题#e#

说明:

(01) Producer是“出产者”类,它与“客栈(depot)”关联。当挪用“出产 者”的produce()要领时,它会新建一个线程并向“客栈”中出产产物。

(02) Customer是“消费者”类,它与“客栈(depot)”关联。当挪用“消费 者”的consume()要领时,它会新建一个线程并消费“客栈”中的产物。

(03) Depot是“客栈”类,客栈中记录“客栈的容量(capacity)”以及“仓 库中当前产物数目(size)”。

#p#分页标题#e#

 “客栈”类的出产要领produce()和消费要领 consume()要领都是synchronized要领,进入synchronized要领体,意味着这个线程获取到了该“仓 库”工具的同步锁。这也就是说,同一时间,出产者和消费者线程只能有一个能运行。通过同步锁 ,实现了对“残忍”的互斥会见。

对支付产要领produce()而言:当客栈满时,出产者线 程期待,需要期待消费者消费产物之后,出产线程才气出产;出产者线程出产完产物之后,会通过 notifyAll()叫醒同步锁上的所有线程,包罗“消费者线程”,即我们所说的“通知消费 者举办消费”。

对付消费要领consume()而言:当客栈为空时,消费者线程期待,需要期待出产 者出产产物之后,消费者线程才气消费;消费者线程消费完产物之后,会通过notifyAll()叫醒同步锁上 的所有线程,包罗“出产者线程”,即我们所说的“通知出产者举办出产”。

(某一次)运行功效:

Thread-0 produce( 60) --> left=  0, inc= 60, size= 60
Thread-4 produce(110) --> left= 70, inc= 40, size=100
Thread-2 consume( 90) <-- left=  0, dec= 90, size= 10
Thread-3 consume(150) <-- left=140, dec= 10, size=  0
Thread-1 produce(120) --> left= 20, inc=100, size=100
Thread-3 consume(150) <-- left= 40, dec=100, size=  0
Thread-4 produce(110) --> left=  0, inc= 70, size= 70
Thread-3 consume(150) <-- left=  0, dec= 40, size= 30
Thread-1 produce(120) --> left=  0, inc= 20, size= 50

查察本栏目

 

    关键字:


天才代写-代写联系方式