0%

生产者消费者问题

生产者消费者问题中,生产者生产数据,消费者消费数据。为了解藕生产者和消费者的关系,通常会采用共享的数据区域,生产者生产数据后直接放在共享数据区,不需要关心消费者的行为;消费者只需要从共享区中获取数据,不需要关心生产者的行为。共享数据区应具备线程间并发协作的能力:

  1. 如果共享数据区已满,阻塞生产者继续生产数据放置到数据区
  2. 如果共享数据区为空,阻塞消费者继续消费数据

实现生产者消费者问题可以采用三种方法:

  1. 用Object的wait/notify消息通知机制
  2. 用Lock的Condition的wait/signal消息通知机制
  3. 用BlockingQueue实现

wait/notify实现

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
63
64
65
public static void main(String[] args) {
ExecutorService executor = new ThreadPoolExecutor(8, 8, 300,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(8), new ThreadPoolExecutor.DiscardPolicy());
List<String> list = new ArrayList<String>();
for(int i = 0; i < 4; ++i) {
executor.submit(new Consumer(list));
}
for(int i = 0; i < 4; ++i) {
executor.submit(new Producer(list, 10));
}
while(!executor.isTerminated()) {
;
}
}

static class Producer implements Runnable {
private List<String> list;
private int maxLength;
public Producer(List<String> list, int maxLength) {
this.list = list;
this.maxLength = maxLength;
}

@Override
public void run() {
while(true) {
try {
synchronized(list) {
while(list.size() > maxLength) {
list.wait();
}
list.add(Thread.currentThread().getName());
list.notifyAll();
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}

static class Consumer implements Runnable {
private List<String> list;

public Consumer(List<String> list) {
this.list = list;
}

@Override
public void run() {
while (true) {
try {
synchronized (list) {
while (list.isEmpty()) {
list.wait();
}
System.out.println(list.remove(0));
list.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Lock/Condition实现

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@Test
public void testProducerConsumer() {
List<String> list = Lists.newArrayList();
ReentrantLock lock = new ReentrantLock();
Condition full = lock.newCondition();
Condition empty = lock.newCondition();

ExecutorService executor = new ThreadPoolExecutor(8, 8, 30, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1), new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 4; ++i) {
executor.submit(new Producer(list, 100, lock, full, empty));
}
for (int i = 0; i < 4; ++i) {
executor.submit(new Consumer(list, lock, full, empty));
}
while (!executor.isTerminated()) {
;
}
}

private static class Consumer implements Runnable {
private List<String> list;
private Lock lock;
private Condition full;
private Condition empty;

public Consumer(List<String> list, Lock lock, Condition full, Condition empty) {
this.list = list;
this.lock = lock;
this.full = full;
this.empty = empty;
}

@Override
public void run() {
while (true) {
try {
lock.lock();
while (list.isEmpty()) {
empty.await();
}
String element = list.remove(0);
System.out.println(element);
full.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}

private static class Producer implements Runnable {
private List<String> list;
private Integer maxLength;
private Random random;
private Lock lock;
private Condition full;
private Condition empty;

public Producer(List<String> list, int maxLength, Lock lock, Condition full, Condition empty) {
this.list = list;
this.lock = lock;
this.maxLength = maxLength;
this.random = new Random(System.currentTimeMillis());
this.full = full;
this.empty = empty;
}

@Override
public void run() {
while (true) {
try {
lock.lock();
while (list.size() >= maxLength) {
full.await();
}
double d = random.nextGaussian();
list.add(Thread.currentThread().getName() + " " + d);
empty.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}

BlockingQueue

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
@Test
public void testProducerConsumer() {
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(100);
ExecutorService executor = new ThreadPoolExecutor(8, 8, 300, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 4; ++i) {
executor.submit(new Producer(queue));
}
for (int i = 0; i < 4; ++i) {
executor.submit(new Consumer(queue));
}
while (!executor.isTerminated()) {
;
}
}


private static class Producer implements Runnable {
private BlockingQueue<String> queue;

public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}

@Override
public void run() {
while (true) {
queue.offer(Thread.currentThread().getName());
}
}
}

private static class Consumer implements Runnable {
private BlockingQueue<String> queue;

public Consumer(BlockingQueue<String> queue) {
this.queue = queue;
}

@Override
public void run() {
while (true) {
String s = queue.poll();
System.out.println(s);
}
}
}

参考资料

一篇文章,让你彻底弄懂生产者–消费者问题