ReentrantLock 实现生产者消费者模式
实现生产者消费者模式:一对一交替打印
public class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean hasValue = false;
public void set() {
try {
lock.lock();
while (hasValue == true) {
condition.await();
}
System.out.println("打印 *");
hasValue = true;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void get() {
try {
lock.lock();
while (hasValue == false) {
condition.await();
}
System.out.println("打印 o");
hasValue = false;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class ThreadA extends Thread {
private MyService myService;
public ThreadA(MyService myService) {
super();
this.myService = myService;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.set();
}
}
}
public class ThreadB extends Thread {
private MyService myService;
public ThreadB(MyService myService) {
super();
this.myService = myService;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
myService.get();
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyService myService = new MyService();
ThreadA a = new ThreadA(myService);
a.setName("A");
a.start();
ThreadB b = new ThreadB(myService);
b.setName("B");
b.start();
}
}
程序输出结果:
// 通过使用Condition对象,成功实现交替打印的效果
打印 o
打印 *
打印 o
打印 *
打印 o
打印 *
实现生产者消费者模式:多对多交替打印
public class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean hasValue = false;
public void set() {
try {
lock.lock();
while (hasValue == true) {
System.out.println("有可能**连续");
condition.await();
}
System.out.println("打印 *");
hasValue = true;
// 造成程序假死
// condition.signal();
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void get() {
try {
lock.lock();
while (hasValue == false) {
System.out.println("有可能oo连续");
condition.await();
}
System.out.println("打印 o");
hasValue = false;
// 造成程序假死
// condition.signal();
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
MyService myService = new MyService();
ThreadA[] threadA = new ThreadA[10];
ThreadB[] threadB = new ThreadB[10];
for (int i = 0; i < 10; i++) {
threadA[i] = new ThreadA(myService);
threadB[i] = new ThreadB(myService);
threadA[i].start();
threadB[i].start();
}
// 使用condition.signal()运行后出现假死
// 根据第3章中的notifyAll()解决方案,可以使用signalAll()方法来解决.
// 将MyService.java类中的两处signal()代码改成signalAll()后,程序得到正确运行
}
}
程序输出:
打印 o
有可能oo连续
有可能oo连续
有可能oo连续
打印 *
有可能**连续
有可能**连续
有可能**连续
打印 o
有可能oo连续
有可能oo连续
有可能oo连续
打印 *
有可能**连续
有可能**连续
控制台中"打印*" 和"打印o"是交替输出的,但是"有可能** 连续" 和 "有可能oo连续"却不是交替输出的,
有时候出现连续打印的情况.原因是程序中使用了一个Condition对象,再结合signalAll()方法来唤醒所有的线程,
那么唤醒的线程就有可能是 同类,所以就出现连续打印"有可能**连续" 或 "有可能oo连续"的情况了.