多线程之生产者与消费者问题

2017-12-15  本文已影响0人  ihujian

生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。

线程之间的状态转换: 线程状态.PNG

生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系。比如一个人正在准备食物(生产者),而另一个人正在吃(消费者),他们使用一个共用的桌子用于放置盘子和取走盘子,生产者准备食物,如果桌子上已经满了就等待,消费者(那个吃的)等待如果桌子空了的话。这里桌子就是一个共享的对象。

现在用代码实现这一场景。
情景一:一个消费者和一个生产者,当生产者生产一个,消费者消费一个。
首先定义资源

package com.ihujian.thread;

/**
 * 
 * Created by Administrator on 2017/12/15.
 */
public class Resource {
    private String name;
    private int count = 1;
    private boolean flag = false;
    public synchronized void set(String name){
        if(flag){
            try {
                this.wait();
            }catch (Exception e){

            }
        }
        this.name = name + "----"+ count++;

        System.out.println(Thread.currentThread().getName() + "。。。生产者。。"+this.name);

        flag = true;
        this.notify();
    }

    public synchronized void out(){
        if(!flag){
            try {
                this.wait();
            }catch (Exception e){

            }
        }
        System.out.println(Thread.currentThread().getName() +"....消费者..."+this.name);
        flag = false;
        this.notify();
    }

}

定义生产者类

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Producer implements Runnable {
    private Resource res;

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

    @Override
    public void run() {
        while (true){
            res.set("+商品+");
        }
    }
}

定义消费者类

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Consumer implements Runnable {
    private Resource res;

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

    @Override
    public void run() {
        while (true){
            res.out();
        }
    }
}

测试结果

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Demo3 {
    public static void main(String[] args) {
        Resource res = new Resource();
        new Thread(new Producer(res)).start();
        new Thread(new Consumer(res)).start();
    }
}

在这里如果是多个生产者和消费者,需要将两个方法的if改成while循环判断标记,并且讲notify()改成notifyAll()唤醒所有线程。 因为如果有多个生产者和消费者的话,使用notify()可能会唤醒己方线程,最终导致所有线程都等待

现在用jdk1.5的Lock接口来实现多消费者和多生产者的情景

定义资源类

package com.ihujian.thread;

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

/**
 * jdk1.5提供了多线程的升级解决方案
 * 将同步synchronized替换成现实Lock操作
 * 将Object中的wait,notify,notifyAll替换了Condition对象,该对象可以通过Lock锁获取
 * Created by Administrator on 2017/12/15.
 */
public class Resource2 {
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();
    private Condition condition_pro = lock.newCondition();
    private Condition condition_con = lock.newCondition();

    public void set(String name) throws InterruptedException {
        lock.lock();
        try {
            while (flag) {
                condition_pro.await();
            }
            this.name = name + "----" + count++;

            System.out.println(Thread.currentThread().getName() + "。。。生产者。。" + this.name);

            flag = true;
            condition_con.signal();
        }finally {

            lock.unlock();
        }
    }

    public void out() throws InterruptedException {
        lock.lock();
        try {

            while (!flag) {
                condition_con.await();
            }
            System.out.println(Thread.currentThread().getName() + "....消费者..." + this.name);
            flag = false;
            condition_pro.signal();
        }finally {
            lock.unlock();
        }
    }
}

生产者类

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Producer2 implements Runnable {
    private Resource2 res;

    public Producer2(Resource2 res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true){
            try {
                res.set("+商品+");
            } catch (InterruptedException e) {
            }
        }
    }
}

消费者类

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Consumer2 implements Runnable {
    private Resource2 res;

    public Consumer2(Resource2 res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true){
            try {
                res.out();
            } catch (InterruptedException e) {
            }
        }
    }
}

测试结果

package com.ihujian.thread;

/**
 * Created by Administrator on 2017/12/15.
 */
public class Demo4 {
    public static void main(String[] args) {
        Resource2 resource2 = new Resource2();

        new Thread(new Producer2(resource2)).start();
        new Thread(new Producer2(resource2)).start();
        new Thread(new Consumer2(resource2)).start();
        new Thread(new Consumer2(resource2)).start();
    }
}

上一篇 下一篇

猜你喜欢

热点阅读