问题:什么是保护性暂停设计模式?有何作用?
–解答:保护性暂停设计模式是一种维护线程间同步的的方法,比如需要在线程间传递某个数据,线程A只有获得该数据才能继续执行。这时就可以使用保护性暂停,让线程A进入等待状态直到数据到达并被唤醒,线程A继续执行。需要注意的是当线程间有多个数据需要传递时,保护性暂停设计模式无法满足需求,需要使用消息队列进行设计。
具体案例:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package com.deng;
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest @Slf4j public class Test2 { public static void main(String[] args) { GuardedObject guardedObject = new GuardedObject();
new Thread(() -> { Object o = guardedObject.get(2000); System.out.println(o); },"t1").start(); try { Thread.sleep(3000); } catch (InterruptedException e) { throw new RuntimeException(e); }
guardedObject.put(); } }
@Slf4j class GuardedObject{ private Object result = null;
public Object get(long timeout){ long begin = System.currentTimeMillis(); synchronized (this){ long passTime = System.currentTimeMillis() - begin; while(result == null){ if(passTime > timeout)break; try { wait(timeout - passTime); } catch (InterruptedException e) { throw new RuntimeException(e); } passTime = System.currentTimeMillis() - begin; } } return result; }
public void put(){ synchronized (this){ result = new Object(); notifyAll(); } } }
|
以上代码使用保护性暂停设计模式模拟了这样一个场景:线程A等待线程B的输入,当A等待时间超过了给定的等待时间时,线程A不再等待,直接返回null。在java中如果你研究过join的源码,你会发现在join中也使用了这种机制。
问题:什么是生产者-消费者模式?适用于什么场景?如何实现?
–解答:生产者-消费者模式是一种模型,这种模式不仅应用在计算机中,在生活中也有很多体现。具体来说模拟的是这样一种场景:一个人专门负责生产产品(生产者),另一个人负责处理产品(消费者)。两者的工作是异步的,能够很好的解耦,两者通过某个中间站实现交互(称为消息队列)。这里面有一些规范,比如生产者只有在容器还未满的情况下才能向容器中放入产品,而消费者只有在容器不空的情况下才能从容器中取出产品。同样,这种模型也可以用于线程间的交互,以下就是一个使用该模式实现线程间交互的例子。
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| @Slf4j @SpringBootTest public class ProducerAndConsumerTest { public static void main(String[] args) throws InterruptedException { ProducerAndConsumerModle producerAndConsumerModle = new ProducerAndConsumerModle(); new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } for(int i = 0; i < 3; i ++){ new Thread(() -> { try { producerAndConsumerModle.producer(); } catch (InterruptedException e) { throw new RuntimeException(e); } },"t" + i).start(); } },"t4").start();
producerAndConsumerModle.consumer(); } } @Slf4j class ProducerAndConsumerModle{ private static final LinkedList<Integer> list = new LinkedList<>(); public void producer() throws InterruptedException { synchronized (this){ System.out.println("开始生产产品"); while(list.size() == 2){ System.out.println("容器已满,只能存储2个物品"); try { wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } list.addFirst(1); System.out.println("已放入产品"); notifyAll(); } }
public void consumer(){ System.out.println("开始处理产品"); synchronized (this){ while(list.isEmpty()){ System.out.println("容器为空,无产品处理"); try { wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } Integer integer = list.removeLast(); System.out.println("已处理产品" + integer); notifyAll(); } } }
|
