只有同步监听对象才能够调用 wait() 和 notify() 方法,不然报错
线程之间进行通讯,且防止耦合度太高,使用一个中间类做为通讯的共同资源java
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(); } } }
须要注意的是,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(); } } }