Java 多线程等待/通知案例——生产者与消费者1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41723615/article/details/88745993

生产者/消费者模式实现
等待/通知模式最经典的案例就是生产者/消费者模式。

以下为生产者与消费者的几种变形。

  • 1.一生产者与一消费者:操作值
  • 2.多生产者与多消费:操作值-假死
  • 3.多生产者与多消费:操作值
  • 4.一生产与一消费:操作栈
  • 5.一生产与多消费——操作栈:解决wait条件改变与假死
  • 6.多生产与一消费:操作栈
  • 7.多生产与多消费:操作栈

1.一生产者与一消费者:操作值

//生产者
public class P {

	private String lock;
	public P(String lock){
		super();
		this.lock = lock;
	}
	
	public void setValue() {
		try {
			synchronized (lock) {
			    if (!ValueObject.value.equals("")) {
					lock.wait();
				}	
			    String value = System.currentTimeMillis() +
			    		"_" + System.nanoTime();
			    System.out.println("set的值是" + value);
			    ValueObject.value = value;
			    lock.notify();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

//生产者
public class C {

	private String lock;
	public C(String lock){
		super();
		this.lock = lock;
	}
	
	public void getValue() {
		try {
			synchronized (lock) {
			    if (ValueObject.value.equals("")) {
					lock.wait();
				}	
			    System.out.println("get的值是" + ValueObject.value);
			    ValueObject.value = "";
			    lock.notify();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

//存储值对象
public class ValueObject {

	public static String value = "";
}
public class ThreadP extends Thread {

	private P p;
	public ThreadP(P p) {
		super();
		this.p = p;
	}
	@Override
	public void run() {
		while (true) {
			p.setValue();;
		}
	}
}
public class ThreadC extends Thread {

	private C r;
	public ThreadC(C r) {
		super();
		this.r = r;
	}
	@Override
	public void run() {
		while (true) {
			r.getValue();
		}
	}
}
public class Run {

	public static void main(String[] args) {

		String lock = new String("");
		P p = new P(lock);
		C r = new C(lock);
		ThreadP pThread = new ThreadP(p);
		ThreadC cThread = new ThreadC(r);
		pThread.start();
		cThread.start();
	}

}

在这里插入图片描述
2.多生产者与多消费:操作值-假死
假死的现象其实就是线程进入waiting等待状态。如果全部线程都进入waiting状态,则程序就不再执行任何业务功能了,整个项目呈停止状态。
修改生产者与消费者类

//生产者

public class P {

private String lock;
public P(String lock){
	super();
	this.lock = lock;
}

public void setValue() {
	try {
		synchronized (lock) {
		    while (!ValueObject.value.equals("")) {
		    	System.out.println("生产者" + 
		    Thread.currentThread().getName() + "WAITING 了★");
				lock.wait();
			}	
		    System.out.println("生产者" + Thread.currentThread().getName()
		    		+System.nanoTime());
		    String value = System.currentTimeMillis() +
		    		"_" + System.nanoTime();
		    System.out.println("set的值是" + value);
		    ValueObject.value = value;
		    lock.notify();
		}
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}

}

//生产者
public class C {

	private String lock;
	public C(String lock){
		super();
		this.lock = lock;
	}
	
	public void getValue() {
		try {
			synchronized (lock) {
			    while (ValueObject.value.equals("")) {
			    	System.out.println("生产者" + 
						    Thread.currentThread().getName() + "WAITING 了☆");
			    	lock.wait();
				}	
			    System.out.println("生产者" + Thread.currentThread().getName()
			    		+ " RUNNABLE了");
			    ValueObject.value = "";
			    lock.notify();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

修改main()方法

public static void main(String[] args)throws InterruptedException {

		String lock = new String("");
		P p = new P(lock);
		C r = new C(lock);
		ThreadP[] pThread = new ThreadP[2];
		ThreadC[] cThread = new ThreadC[2];
		for (int i = 0; i < 2; i++) {
			pThread[i] = new ThreadP(p);
			pThread[i].setName("生产者" + (i + 1));
			cThread[i] = new ThreadC(r);
			cThread[i].setName("消费者" + (i + 1));
			pThread[i].start();
			cThread[i].start();
		}
		Thread.sleep(5000);
		Thread[] threadArray = new Thread[
			Thread.currentThread().getThreadGroup().activeCount()
		];
		Thread.currentThread().getThreadGroup().enumerate(threadArray);
		for (int i = 0; i < threadArray.length; i++) {
			System.out.println(threadArray[i].getName() + " " + 
		threadArray[i].getState());
		}
	}

在这里插入图片描述
在代码中确实已经通过wait/notify进行通信了,但不保证notify唤醒的是异类,也许是同类,比如生产者唤醒生产者,或者消费者唤醒消费者这样的情况。如果按这样情况运行的比率积少成多,就会导致所有的线程都不能继续运行下去,大家都在等待,都呈WAITING状态,程序最后也就是呈假死状态,就不能继续运行下去了。

3.多生产者与多消费:操作值
怎么解决上面的假死情况呢,将notify()方法改为notifyAll()方法即可。
此原理就是同类和异类一起通知。

猜你喜欢

转载自blog.csdn.net/qq_41723615/article/details/88745993