1、wait & notify 方法:
public class WaitAndNotify {
private final int MAX_SIZE = 100;
private LinkedList<Object> list = new LinkedList<Object>();
public void produce(int num)
{
synchronized (list)
{
while (list.size() + num > MAX_SIZE)
{
System.out.println("要生产的产品数:" + num + ", 现库存量为:"
+ list.size() + " 不能继续生产!");
try
{
list.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int i = 1; i <= num; ++i)
{
list.add(new Object());
System.out.println("已生产产品数:" + num + ", 现产品量为:" + list.size());
}
list.notifyAll();
}
}
public void consume(int num)
{
synchronized (list)
{
while (list.size() < num)
{
System.out.println("要消费的产品量:" + num + ", 现库存量为:"
+ list.size() + ",存量不足,暂时不能消费!");
try
{
list.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int i = 1; i <= num; ++i)
{
list.remove();
System.out.println("已消费产品数" + num + ", 现存量为:" + list.size());
}
list.notifyAll();
}
}
}
public class Producer implements Runnable{
private int num;
private WaitAndNotify storage;
public Producer(WaitAndNotify storage)
{
this.storage = storage;
}
public void run()
{
produce(num);
}
public void produce(int num)
{
storage.produce(num);
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
public WaitAndNotify getStorage()
{
return storage;
}
public void setStorage(WaitAndNotify storage)
{
this.storage = storage;
}
}
public class Consumer implements Runnable{
private int num;
private WaitAndNotify storage;
public Consumer(WaitAndNotify storage)
{
this.storage = storage;
}
public void run()
{
consume(num);
}
public void consume(int num)
{
storage.consume(num);
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
public WaitAndNotify getStorage()
{
return storage;
}
public void setStorage(WaitAndNotify storage)
{
this.storage = storage;
}
}
public class WaitAndNotifyTest {
public static void main(String[] args) {
WaitAndNotify storage = new WaitAndNotify();
Producer p1 = new Producer(storage);
Producer p2 = new Producer(storage);
Producer p3 = new Producer(storage);
p1.setNum(10);
p2.setNum(20);
p3.setNum(30);
Consumer c1 = new Consumer(storage);
Consumer c2 = new Consumer(storage);
c1.setNum(15);
c2.setNum(20);
p1.run();
p2.run();
c1.run();
c2.run();
p3.run();
}
}
运行结果如下:
已生产产品数:10, 现产品量为:1
已生产产品数:10, 现产品量为:2
已生产产品数:10, 现产品量为:3
已生产产品数:10, 现产品量为:4
已生产产品数:10, 现产品量为:5
已生产产品数:10, 现产品量为:6
已生产产品数:10, 现产品量为:7
已生产产品数:10, 现产品量为:8
已生产产品数:10, 现产品量为:9
已生产产品数:10, 现产品量为:10
已生产产品数:20, 现产品量为:11
已生产产品数:20, 现产品量为:12
已生产产品数:20, 现产品量为:13
已生产产品数:20, 现产品量为:14
已生产产品数:20, 现产品量为:15
已生产产品数:20, 现产品量为:16
已生产产品数:20, 现产品量为:17
已生产产品数:20, 现产品量为:18
已生产产品数:20, 现产品量为:19
已生产产品数:20, 现产品量为:20
已生产产品数:20, 现产品量为:21
已生产产品数:20, 现产品量为:22
已生产产品数:20, 现产品量为:23
已生产产品数:20, 现产品量为:24
已生产产品数:20, 现产品量为:25
已生产产品数:20, 现产品量为:26
已生产产品数:20, 现产品量为:27
已生产产品数:20, 现产品量为:28
已生产产品数:20, 现产品量为:29
已生产产品数:20, 现产品量为:30
已消费产品数15, 现存量为:29
已消费产品数15, 现存量为:28
已消费产品数15, 现存量为:27
已消费产品数15, 现存量为:26
已消费产品数15, 现存量为:25
已消费产品数15, 现存量为:24
已消费产品数15, 现存量为:23
已消费产品数15, 现存量为:22
已消费产品数15, 现存量为:21
已消费产品数15, 现存量为:20
已消费产品数15, 现存量为:19
已消费产品数15, 现存量为:18
已消费产品数15, 现存量为:17
已消费产品数15, 现存量为:16
已消费产品数15, 现存量为:15
要消费的产品量:20, 现库存量为:15,存量不足,暂时不能消费!
这里有个问题:为了唤醒正在等待的线程,应该使用notify还是notifyAll?
一般情况下,应该使用notifyAll,这是合理而保守的建议,它总会产生正确的结果,因为它可以保证将会唤醒所有需要被唤醒的线程。可能会唤醒一些其他的线程,但这不会影响程序的正确性,这些线程醒来之后,会检查他们正在等待的条件,如果发现条件并不满足,就会继续等待。
从优化的角度来讲,如果处于等待状态的所有线程都在等待同一个条件,而每次只有一个线程可以从这个条件被唤醒,那么就应该选择notify,而不是notifyAll。
2、BlockingQueue方法:
直接使用wait和notify就像用“并发编程语言”进行编程一样,而java.util.concurrent则提供了更高级的语言,没有理由在新代码中使用wait和notify.即使有,也是极少的。下面我们对比一下阻塞队列方法BlockingQueue,它是java.util.concurrent下的主要用来控制线程同步的工具。
public class BlockingQueue
{
private final int MAX_SIZE = 100;
private LinkedBlockingQueue<Object> productList = new LinkedBlockingQueue<Object>(100);
public void Produce(int num)
{
if (productList.size() == MAX_SIZE)
{
System.out.println("生产库存量为:" + MAX_SIZE + ",库存已满,暂时无法生产!");
}
for (int i = 1; i <= num; ++i)
{
try
{
productList.put(new Object());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("生产库存量为:" + productList.size());
}
}
public void Consume(int num)
{
if (productList.size() == 0)
{
System.out.println("消费库存量为0,暂时不能消费!");
}
for (int i = 1; i <= num; ++i)
{
if (productList.size() < num)
{
System.out.println(
"要消费的产品量:" + num + ", 现库存量为:" + productList.size() + ",存量不足,不能消费!");
}
try
{
productList.take();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("消费库存量:" + productList.size());
}
}
public class Producer implements Runnable {
private int num;
private BlockingQueue storage;
public Producer(BlockingQueue storage)
{
this.storage = storage;
}
public void run()
{
produce(num);
}
public void produce(int num)
{
storage.Produce(num);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public BlockingQueue getStorage() {
return storage;
}
public void setStorage(BlockingQueue storage) {
this.storage = storage;
}
}
public class Consumer implements Runnable{
private int num;
private BlockingQueue storage;
public Consumer(BlockingQueue storage)
{
this.storage = storage;
}
public void run()
{
consume(num);
}
public void consume(int num)
{
storage.Consume(num);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public BlockingQueue getStorage() {
return storage;
}
public void setStorage(BlockingQueue storage) {
this.storage = storage;
}
}
public class BlockingQueueTest {
public static void main(String[] args) {
BlockingQueue storage = new BlockingQueue();
Producer p1 = new Producer(storage);
Producer p2 = new Producer(storage);
Producer p3 = new Producer(storage);
p1.setNum(10);
p2.setNum(20);
p3.setNum(30);
Consumer c1 = new Consumer(storage);
Consumer c2 = new Consumer(storage);
c1.setNum(15);
c2.setNum(20);
p1.run();
p2.run();
c1.run();
c2.run();
p3.run();
}
}
运行结果如下:
生产库存量为:1
生产库存量为:2
生产库存量为:3
生产库存量为:4
生产库存量为:5
生产库存量为:6
生产库存量为:7
生产库存量为:8
生产库存量为:9
生产库存量为:10
生产库存量为:11
生产库存量为:12
生产库存量为:13
生产库存量为:14
生产库存量为:15
生产库存量为:16
生产库存量为:17
生产库存量为:18
生产库存量为:19
生产库存量为:20
生产库存量为:21
生产库存量为:22
生产库存量为:23
生产库存量为:24
生产库存量为:25
生产库存量为:26
生产库存量为:27
生产库存量为:28
生产库存量为:29
生产库存量为:30
消费库存量:15
要消费的产品量:20, 现库存量为:15,存量不足,不能消费!
要消费的产品量:20, 现库存量为:14,存量不足,不能消费!
要消费的产品量:20, 现库存量为:13,存量不足,不能消费!
要消费的产品量:20, 现库存量为:12,存量不足,不能消费!
要消费的产品量:20, 现库存量为:11,存量不足,不能消费!
要消费的产品量:20, 现库存量为:10,存量不足,不能消费!
要消费的产品量:20, 现库存量为:9,存量不足,不能消费!
要消费的产品量:20, 现库存量为:8,存量不足,不能消费!
要消费的产品量:20, 现库存量为:7,存量不足,不能消费!
要消费的产品量:20, 现库存量为:6,存量不足,不能消费!
要消费的产品量:20, 现库存量为:5,存量不足,不能消费!
要消费的产品量:20, 现库存量为:4,存量不足,不能消费!
要消费的产品量:20, 现库存量为:3,存量不足,不能消费!
要消费的产品量:20, 现库存量为:2,存量不足,不能消费!
要消费的产品量:20, 现库存量为:1,存量不足,不能消费!
要消费的产品量:20, 现库存量为:0,存量不足,不能消费!