问题:什么是保护性暂停设计模式?有何作用?

​ –解答:保护性暂停设计模式是一种维护线程间同步的的方法,比如需要在线程间传递某个数据,线程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;

/**
* GuardedObject扩展超时机制
* @param timeout
* @return
*/
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();
}
}
}

image-20240318161119296