生产者-消费者问题
a. 在多线程程序中,可能出现生产者-消费者问题,即等待同步数据的问题
b. 可能出现的问题:
a) 生产者比消费者快时,消费者会漏掉一些数据没有取到
b) 消费者比生产者快时,消费者取相同的数据
c. notify()和wait()方法用来协调读取的关系
d. notify()和wait()都只能从同步方法中调用
实例:
产品:
package com.bijian.thread;
public class Shared {
private char c = '\u0000';
void setSharedChar(char c) {
this.c = c;
}
char getSharedChar() {
return c;
}
}
生产者:
package com.bijian.thread;
public class Producer extends Thread {
private Shared s;
Producer(Shared s) {
this.s = s;
}
public void run() {
for (char ch = 'A'; ch <= 'Z'; ch++) {
try {
Thread.sleep((int) (Math.random() * 4000));
} catch (InterruptedException e) {
}
s.setSharedChar(ch);
System.out.println(ch + " produced by producer.");
}
}
}
消费者:
package com.bijian.thread;
public class Consumer extends Thread {
private Shared s;
Consumer(Shared s) {
this.s = s;
}
public void run() {
char ch;
do {
try {
Thread.sleep((int) (Math.random() * 4000));
} catch (InterruptedException e) {
}
ch = s.getSharedChar();
System.out.println(ch + " consumed by consumer.");
} while (ch != 'Z');
}
}
主线程类:
package com.bijian.thread;
public class ProdCons {
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
运行结果:
A produced by producer. A consumed by consumer. B produced by producer. B consumed by consumer. B consumed by consumer. C produced by producer. C consumed by consumer. C consumed by consumer. C consumed by consumer. D produced by producer. …
上面是一种运行结果,出现了消费者比生产者快,消费者取相同的数据C的问题。
为解决此问题,修改Shared类如下(方法增加同步锁,且增加writeable域变量控制放一个值、取一个值,再放下一个值、取下一个值的,…,整个过程)
package com.bijian.thread;
public class Shared {
private char c = '\u0000';
private boolean writeable = true;
synchronized void setSharedChar(char c) {
if (!writeable)
try {
wait();
} catch (InterruptedException e) {
}
this.c = c;
writeable = false;
System.out.println(Thread.currentThread().getName() + ": " + c + " produced by producer.");
notify();
}
synchronized char getSharedChar() {
if (writeable)
try {
wait();
} catch (InterruptedException e) {
}
writeable = true;
notify();
System.out.println(Thread.currentThread().getName() + ": " + c + " consumed by consumer.");
return c;
}
}
运行结果:
Thread-0: A produced by producer. Thread-1: A consumed by consumer. Thread-0: B produced by producer. Thread-1: B consumed by consumer. Thread-0: C produced by producer. Thread-1: C consumed by consumer. Thread-0: D produced by producer. Thread-1: D consumed by consumer. …