线程通讯之生产者和消费者案例

使用 Object 类的 wait() 和 notify() 方法 (不适用锁机制)

只有同步监听对象才能够调用 wait() 和 notify() 方法,不然报错
线程之间进行通讯,且防止耦合度太高,使用一个中间类做为通讯的共同资源java

  • 须要使用 synchronized 保证一个过程的原子性
  • 使用 isEmpty 变量做为标志参数,在结束生产和结束消费以后改变该值
  • 使用 Object 类的 wait() 方法,判断资源状态,若存在则当前进程进入等待池
  • 使用 Object 类的 notify() 方法,在结束生产和结束消费以后唤醒其余线程
  • 值得注意的是:只有同步监听对象才能够调用 wait() 和 notify() 方法,不然报错

测试类

source 做为两个线程的参数传入ide

public class TestDemo {
    public static void main(String[] args) {
        ShareSources source = new ShareSources();
        new Producer(source).start();
        new Comsumer(source).start();
    }
}

资源类

public class ShareSources {
    private String name;
    private String sex;
    private Boolean isEmpty = true;//使用一个参数做为标志

    /**
     * 存入数据
     * @param name
     * @param sex
     */
    synchronized public void push(String name, String sex) {//同步方法,保证了该方法的原子性
        try {
            //此处使用While比If更加合理,
            while (!isEmpty) {// 生产者是当前线程,若是资源任存在,则当前线程释放锁,进入等待池中,释放后,消费者进程得到锁
                this.wait();//this 指的是 source 对象 进入等待池中的线程只能被其余线程唤醒,这里只能在消费者线程中唤醒
            }
            //---------------------开始生产-------------------------
            this.name = name;
            Thread.sleep(10);
            this.sex = sex;
            //---------------------结束生产-------------------------
            isEmpty = false;
            this.notifyAll();//同时将其余线程唤醒
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取资源
     */
    synchronized public void get() {
        try {
            while (isEmpty) {//若是资源不存在
                this.wait();//当前线程是消费者,进入等待池
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //---------------------开始消费-------------------------
        Thread.sleep(10);       
        System.out.println(this.name + "-" + this.sex);
        //---------------------结束消费-------------------------
        isEmpty = true;
        this.notifyAll();//同时将其余线程唤醒
    }
}

生产者类

生产者可能存在多个,且须要与消费者不一样线程测试

public class Producer extends Thread {
    private ShareSources source = null;

    public Producer(ShareSources source) {//经过构造器获取相同的资源
        this.source = source;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            if (i % 2 == 0) {
                source.push("春哥", "男");
            }else {
                source.push("凤姐", "女");
            }
        }
    }
}

消费者类

public class Comsumer extends Thread {
    private ShareSources source = null;

    public Comsumer(ShareSources source) {
        this.source = source;
    }

    public void run() {
        for (int i = 0; i < 50; i++) {
            source.get();
        }
    }
}

使用 Lock 和 condition 接口

资源类(只有该类发生变化)

须要注意的是,condition 的操做必定要在获取锁以后,释放锁以前执行,不然报错this

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

public class ShareSources {
    private String name;
    private String sex;
    private Boolean isEmpty = true;
    // 实例化锁
    private final Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();// 因为Condition是一个接口,lock.newCondition()方法返回一个绑定的Condition实例

    /**
     * 存入数据
     * 
     * @param name
     * @param sex
     */
    public void push(String name, String sex) {
        lock.lock();
        try {
            if (!isEmpty) {
                condition.await();// 使用condition的await()方法至关于 Object 类的 wait 方法
            }
            this.name = name;
            Thread.sleep(10);
            this.sex = sex;
            isEmpty = false;
            condition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 获取资源
     */
    public void get() {
        lock.lock();
        try {
            if (isEmpty) {
                condition.await();// 使用condition的await()方法至关于 Object 类的 wait 方法
            }
            Thread.sleep(10);
            System.out.println(this.name + "-" + this.sex);
            isEmpty = true;
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
相关文章
相关标签/搜索