一、实现生产者/消费者模式
1、一生产与一消费:操作值
(1)利用synchronized 实现,代码如下:
public class Producer {
private String lock;
public Producer(String lock){
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 Consumer {
private String lock;
public Consumer(String lock){
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 Producer producer;
public ThreadP(Producer producer){
this.producer = producer;
}
@Override
public void run(){
while(true){
producer.setValue();
}
}
}
public class ThreadC extends Thread{
private Consumer consumer;
public ThreadC(Consumer consumer){
this.consumer = consumer;
}
@Override
public void run(){
while(true){
consumer.getValue();
}
}
}
public class PAndC {
public static void main(String[] args) throws InterruptedException{
String lock = new String("");
Producer p = new Producer(lock);
Consumer c = new Consumer(lock);
ThreadP threadP = new ThreadP(p);
ThreadC threadC = new ThreadC(c);
threadP.start();
Thread.sleep(1000);
threadC.start();
}
}
(2) 利用BlockingQueue阻塞队列实现生产者消费者模式,代码如下:
public class ProducerAndConsumer {
private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
private static class Producer extends Thread{
@Override
public void run(){
try {
queue.put("product");
System.out.println("生产,");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class Consumer extends Thread{
@Override
public void run(){
try {
String product = queue.take();
System.out.println("消费。");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
for(int i=0; i<3; i++){
Producer p = new Producer();
p.start();
}
for(int i=0; i<5; i++){
Consumer c = new Consumer();
c.start();
}
for(int i=0; i<2; i++){
Producer p = new Producer();
p.start();
}
}
}
这里利用ArrayBlockingQueue来实现生产者消费者模式,解释下上图后四行可能会出现先打印 “消费。” 后打印 “生产,” 的情况,这是因为有消费者线程阻塞了,等待代码中第三个for循环的生产者线程执行完queue.put(“生产,”)之后,阻塞的消费者线程被唤醒然后抢先打印“消费。”,所以会出现这种情况。
2、一对一交替打印A、B
利用ReentrantLock 与Condition 实现,代码如下:
public class MyService {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean hasValue = false;
public void printA(){
try{
lock.lock();
while(hasValue == true){
condition.await();
}
System.out.println("打印A");
hasValue = true;
condition.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void printB(){
try{
lock.lock();
while(hasValue == false){
condition.await();
}
System.out.println("打印B");
hasValue = false;
condition.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
public class ThreadA extends Thread{
private MyService service;
public ThreadA(MyService service){
this.service = service;
}
@Override
public void run(){
for(int i=0; i<5; i++){//交替打印5对A、B,将5替换为Integer.MAX_VALUE即可不断打印
service.printA();
}
}
}
public class ThreadB extends Thread{
private MyService service;
public ThreadB(MyService service){
this.service = service;
}
@Override
public void run(){
for(int i=0; i<5; i++){
service.printB();
}
}
}
public class ProducersAndConsumers {
public static void main(String[] args) {
MyService service = new MyService();
ThreadA A = new ThreadA(service);
ThreadB B = new ThreadB(service);
A.start();
B.start();
}
}
二、参考
《Java多线程编程核心技术》高洪岩