版权声明:本文为博主原创文章,未经博主允许不得转载。 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()方法即可。
此原理就是同类和异类一起通知。