《Java并行编程实战》ch5 基础构建模块 这章写的真不错,总结了3个有意思的问题。
1. 不使用信号量,实现生产者-消费者问题
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class PC {
public static void main(String[] args) {
BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>(3);
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
class Producer implements Runnable {
private final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> q) {
queue = q;
}
public void run() {
try {
while (true) {
System.out.println("size : " + queue.size());
System.out.println(">> put ");
queue.put(produce());
System.out.println("<< put ");
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
Integer produce() {
int a = (int) (Math.random() * 1000);
System.out.println("Producer produced " + a);
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
return a;
}
}
class Consumer implements Runnable {
private final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> q) {
queue = q;
}
public void run() {
try {
while (true) {
consume(queue.take());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void consume(Integer x) {
try {
System.out.println("Consumer " + Thread.currentThread().getId()
+ " is consuming " + x.intValue());
Thread.sleep(x.intValue());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
size : 0
>> put
Producer produced 396
Consumer 10 is consuming 396
<< put
size : 0
>> put
Producer produced 236
<< put
size : 1
>> put
Producer produced 899
<< put
size : 2
>> put
Producer produced 555
<< put
size : 3
>> put
Producer produced 601
<< put
size : 3
>> put
Producer produced 609
Consumer 9 is consuming 236
Consumer 9 is consuming 899
<< put
size : 3
>> put
Producer produced 561
Consumer 10 is consuming 555
<< put
size : 3
>> put
Producer produced 377
Consumer 10 is consuming 601
<< put
size : 3
>> put
Producer produced 872
Consumer 9 is consuming 609
<< put
size : 3
>> put
Producer produced 818
Consumer 10 is consuming 561
<< put
size : 3
>> put
Producer produced 872
Consumer 9 is consuming 377
<< put
size : 3
>> put
Producer produced 522
<< put
size : 3
>> put
Producer produced 841
Consumer 10 is consuming 872
Consumer 9 is consuming 818
<< put
size : 3
>> put
Producer produced 540
Consumer 9 is consuming 872
<< put
size : 3
>> put
Producer produced 90
Consumer 10 is consuming 522
<< put
size : 3
>> put
Producer produced 576
从上面的结果可以看出,当BlockingQueue满了后,生产者在执行put时会被阻塞住,当消费者从队列里取走一个元素后,生产者的put才会成功返回。
2. 如何让一组线程同时开始?如何等待一组线程全部结束?
CountDownLatch!
3. 如何实现高效的缓存服务器?
ConcurrentHashMap + FutureTask