存在问题
像前面实现消费者生产者例程那样,地址,直接操作线程这种方式是可以的,但对于并发编程,这样的代码很快变得容易出错,特别是好几个线程需要协作来完成一个更大的任务的时候。这种情况下,它们的控制流需要被协调。
例如,一个线程的执行完成可能依赖于其他将要执行完成的线程。通常熟悉的例子就是生产者/消费者的例子,因为如果消费者队列是空的,那么生产者应该等待消费者,并且如果生产者队列是空的,那么消费者也应该等待生产者。该需求可能通过共享状态和条件队列来实现,但是你仍然必须通过使用共享对象上的java.lang.Object.nofity()
和java.lang.Object.wait()
来实现同步,这很容易出错。
最终,一个常见的错误就是在大段代码甚至整个方法上使用synchronize
进行互斥。虽然这种方法能实现线程安全的代码,但是通常由于排斥时间太长而限制了并行性,从而造成性能低下。
用synchronize实现消费者生产者
package com.producerconsumer;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class ProducerConsumerInJava {
public static void main(String args[]) {
System.out.println("How to use wait and notify method in Java");
System.out.println("Solving Producer Consumper Problem");
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
/**
* Producer Thread will keep producing values for Consumer to consumer. It will
* use wait() method when Queue is full and use notify() method to send
* notification to Consumer Thread.
*
*/
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out.println("Queue is full, " + "Producer thread waiting for "
+ "consumer to take something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
/**
* Consumer Thread will consumer values form shared queue. It will also use
* wait() method to wait if queue is empty. It will also use notify method to
* send notification to producer thread after consuming values from queue.
*
*/
class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println("Queue is empty," + "Consumer thread is waiting"
+ " for producer thread to put something in queue");
try {
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
用ReentrantLock实现消费者生产者
package com.toc;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestReentrantLock {
public static void main(String[] args) throws InterruptedException {
System.out.println("How to use await and signal method in Java");
System.out.println("Solving Producer Consumper Problem");
// 锁对象
final Lock lock = new ReentrantLock();
Condition full = lock.newCondition();
Condition empty = lock.newCondition();
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(lock, full, empty, buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(lock, full, empty, buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
class Producer extends Thread {
// 锁对象
private final Lock lock;
// 控制队列满的条件变量
private final Condition full;
// 控制队列空的条件变量
private final Condition empty;
private Queue<Integer> queue;
private int maxSize;
public Producer(Lock lock,Condition full,Condition empty, Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
this.lock = lock;
this.full = full;
this.empty = empty;
}
@Override
public void run() {
while(true){
// 获得锁
lock.lock();
try {
while (queue.size() == maxSize) {
System.out.println("队列满了,等待消费者取走");
// 由于条件不满足,生产阻塞
full.await();
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
empty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
class Consumer extends Thread {
// 锁对象
private final Lock lock;
// 控制队列满的条件变量
private final Condition full;
// 控制队列空的条件变量
private final Condition empty;
private Queue<Integer> queue;
private int maxSize;
public Consumer(Lock lock,Condition full,Condition empty, Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
this.lock = lock;
this.full = full;
this.empty = empty;
}
@Override
public void run() {
// 获得锁
while (true) {
lock.lock();
try{
while (queue.isEmpty()) {
System.out.println("队列空了,等待生产者生产");
empty.await();
}
System.out.println("Consuming value : " + queue.remove());
full.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
}