本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。
1) 线程通信
题目:实现一个容器,提供两个方法,add / size,写两个线程,线程 1 添加 10 个元素到容器中,线程 2 实现监控元素的个数,当个数到 5 个时,线程 2 给出提示并结束。
1.1) 思路:
首先会面临两个问题,add / size 函数的一致性问题,和容器的线程见可见性问题
- 容器选择:两种选择方案,使用普通 list,给 add / size 上锁;或者用 Collections 来生成同步容器
- 可见性问题:遇到可见性问题第一个会想到 volatile,但是 volatile 不能保证元素内部发生改变时的线程间可见性问题。处理方式多种:notify、CountDownLatch、LockSupport 等等,Semaphore 都行。
LockSupport 版,代码少哈哈哈哈哈哈哈哈
public class Thread_Notify {
List<Object> list = Collections.synchronizedList(new ArrayList<>());
static Thread a;
static Thread b;
public void add(Object o) {
list.add(o);
}
public int size() {
return list.size();
}
public static void main(String[] args) {
Thread_Notify instance = new Thread_Notify();
a = new Thread(() -> {
LockSupport.park();
System.out.println("=====5");
LockSupport.unpark(a);
});
b = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
instance.add(i);
System.out.println(i);
if (5 == i) {
LockSupport.unpark(b);
LockSupport.park();
}
}
});
a.start();
b.start();
}
}
2) 线程阻塞
题目:写一个固定容量同步容器,拥有 put 和 get 方法,以及 getCount 方法,能够支持 2 个生产者线程和 10 个消费者线程的阻塞调用。
2.1) 思路
这题本质上是考知识面,是否知道 Condition,可以给容器加个泛型装逼 -。-
public class ThreadCondition {
private final int MAX_SIZE = 10;
private final LinkedList<Object> list = new LinkedList<>();
private int count = 0;
private Lock lock = new ReentrantLock();
Condition producer = lock.newCondition();
Condition consumer = lock.newCondition();
public void put(Object o) {
try {
lock.lock();
while (MAX_SIZE == list.size()) producer.await();
list.add(o);
++count;
consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public Object get() {
Object result = null;
try {
lock.lock();
while (0 == count) consumer.await();
result = list.removeFirst();
--count;
producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return result;
}
public static void main(String[] args) {
ThreadCondition list = new ThreadCondition();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 5; j++) {
System.out.println(list.get());
}
}).start();
}
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < 25; j++) {
list.put(Thread.currentThread().getName() + " - " + j);
}
}, "Producer " + i).start();
}
}
}