使用ReentrantLock和Condition進(jìn)行線程同步,利用不同的Condition可精確指定要喚醒的線程
public class MyContainer<T> {
private LinkedList<T> list = new LinkedList<>();
private int count = 0;
private int max = 10;
private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();
public void put(T t) {
lock.lock();
try {
while (list.size() == max) {
System.out.println("滿啦!" + count);
producer.await();
}
list.add(t);
count++;
consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public T get() {
lock.lock();
T t = null;
try {
while (list.size() == 0) {
System.out.println("空啦!" + count);
consumer.await();
}
t = list.removeFirst();
count--;
producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
}
public static void main(String[] args) throws InterruptedException {
MyContainer<String> container = new MyContainer<>();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 5; j++) {
String s = container.get();
System.out.println(Thread.currentThread().getName() + ":" + s);
}
}, "C" + i).start();
}
TimeUnit.SECONDS.sleep(2);
for (int i = 0; i < 2; i++) {
new Thread(() -> {
for (int j = 0; j < 30; j++) {
container.put(Thread.currentThread().getName() + " " + j);
}
}, "P" + i).start();
}
}
}
main方法執(zhí)行結(jié)果:
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
空啦!0
滿啦!10
滿啦!10
C0:P0 0
C2:P0 1
C1:P0 3
C1:P0 6
C0:P0 2
空啦!0
C6:P0 9
C5:P0 8
C4:P0 7
C3:P0 5
C2:P0 4
空啦!0
空啦!0
空啦!0
滿啦!10
滿啦!10
C1:P0 10
C6:P0 11
C3:P0 14
C4:P0 13
C7:P0 19
C5:P0 12
空啦!0
空啦!0
空啦!0
C0:P0 18
C3:P0 17
C7:P0 22
C5:P0 24
C8:P1 0
C2:P0 16
C6:P0 15
空啦!0
C5:P1 1
C4:P0 26
C2:P0 28
C9:P1 3
C9:P1 6
C7:P0 25
C3:P0 23
C1:P0 21
C0:P0 20
滿啦!10
C5:P1 5
C7:P1 8
C2:P1 4
C6:P1 2
C4:P0 29
C8:P0 27
滿啦!10
C7:P1 12
C0:P1 11
C1:P1 10
C3:P1 9
C9:P1 7
滿啦!10
C8:P1 15
C4:P1 14
C6:P1 13
滿啦!10
C8:P1 17
C8:P1 18
滿啦!10
C9:P1 16
C9:P1 19