线程同步经典问题:生产者消费者问题
例如:创建一个固定容器,实现add 和 put方法。生产者put,同时消费者get。
问题:固定容量.容器0的时候等待生产者put。容器达到最大数量生产者等待,通知消费者消费
private final LinkedList<T> linkedList = new LinkedList();
//固定容器
private final int MAX = 10;
private int count=0;
//当前this对象锁
public synchronized void put(T t) {
while (linkedList.size() == MAX) { //为什么要用while 而不用 if
//因为if只判断一次 多个线程的情况下 会存在list容量溢出的情况
//需要用while判断 循环检查
//
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
linkedList.add(t);
++count;
//为什么不用 notify 是因为唤醒的线程是不确定的,如果唤醒的是生产者那就 会死锁的状态
this.notifyAll();
}
public synchronized T get() {
T t = null;
while (linkedList.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t = linkedList.removeFirst();
count--;
this.notifyAll();//通知生产者生产
return t;
}
public static void main(String[] args) {
synchronized10<String> stringsynchronized10 = new synchronized10<String>();
//消费者
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 5; j++) {
System.out.println(stringsynchronized10.get());
}
}, "c" + i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i=0;i<2;i++){
new Thread(()->{
for (int j=0;j<25;j++){
stringsynchronized10.put(Thread.currentThread().getName()+" "+j);
}
},"p"+i).start();
}
}
另一种实现ReentrantLock实现 Condition可以精确指定,比notifyAll唤醒全部线程效率高
private LinkedList list = new LinkedList();
private static int Max = 10;
private int count = 0;
private Lock lock = new ReentrantLock();
//精确指定 可以理解为队列
Condition product = lock.newCondition();
Condition consumer = lock.newCondition();
public void put(Object o) {
lock.lock();
try {
while (list.size() == Max) {
try {
//生产者等待
product.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(o);
++count;
//唤醒消费者
consumer.signalAll();
} finally {
lock.unlock();
}
}
public Object get() {
Object o = null;
lock.lock();
try {
while (list.size() == 0) {
try {
consumer.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
o = list.removeFirst();
count--;
product.signalAll();
} finally {
lock.unlock();
}
return o;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。