2.使用NotifyAll
而不是使用notify
现象
如果是多消费者和多生产者情况,如果使用notify
方法可能会出现“假死”的情况,即唤醒的是同类线程。
原因分析
假设当前多个生产者线程会调用wait
方法阻塞等待,当其中的生产者线程获取到对象锁之后使用notify
通知处于WAITTING
状态的线程,如果唤醒的仍然是生产者线程,就会造成所有的消费者线程都处于等待状态。
解决方案
使用NotifyAll
而不是使用notify
代码实现如下:
public class ProductorConsumerDemo1 {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 5; i++) {
service.submit(new Productor(linkedList, 8));
}
for (int i = 0; i < 10; i++) {
service.submit(new Consumer(linkedList));
}
}
static class Productor implements Runnable {
private List list;
private int maxLength;
public Productor(List list, int maxLength) {
this.list = list;
this.maxLength = maxLength;
}
@Override
public void run() {
while (true) {
synchronized (list) {
try {
while (list.size() == maxLength) {
System.out.println(“生产者” + Thread.currentThread().getName() + " list以达到最大容量,进行wait");
list.wait();
System.out.println(“生产者” + Thread.currentThread().getName() + " 退出wait");
}
Random random = new Random();
int i = random.nextInt();
System.out.println(“生产者” + Thread.currentThread().getName() + " 生产数据" + i);
list.add(i);
list.notifyAll();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable {
private List list;
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
while (true) {
synchronized (list) {
try {
while (list.isEmpty()) {
System.out.println(“消费者” + Thread.currentThread().getName() + " list为空,进行wait");
list.wait();
System.out.println(“消费者” + Thread.currentThread().getName() + " 退出wait");
}
Integer element = list.remove(0);
System.out.println(“消费者” + Thread.currentThread().getName() + " 消费数据:" + element);
list.notifyAll();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
2.Lock
方式实现
Lock
中的Condition
可以实现上面Object
的wait
,notify
一样的效果
await
对应wait
,signal
对应notify
,signalAll
对应notifyAll
下面直接来看看实现,代码与使用wait
,notify
基本上是一样的,只是同步方式不同
public class ProductorConsumerDemo2 {
private static ReentrantLock lock = new ReentrantLock();
private static Condition full = lock.newCondition();
private static Condition empty = lock.newCondition();
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
ExecutorService service = Executors.newFixedThreadPool(15);
for (int i = 0; i < 5; i++) {
service.submit(new Productor(linkedList, 8, lock));
}
for (int i = 0; i < 10; i++) {
service.submit(new Consumer(linkedList, lock));
}
}
static class Productor implements Runnable {
private List list;
private int maxLength;
private Lock lock;
public Productor(List list, int maxLength, Lock lock) {
this.list = list;
this.maxLength = maxLength;
this.lock = lock;
}
@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.size() == maxLength) {
System.out.println(“生产者” + Thread.currentThread().getName() + " list以达到最大容量,进行wait");
full.await();
System.out.println(“生产者” + Thread.currentThread().getName() + " 退出wait");
}
Random random = new Random();
int i = random.nextInt();
System.out.println(“生产者” + Thread.currentThread().getName() + " 生产数据" + i);
list.add(i);
empty.signalAll();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
static class Consumer implements Runnable {
private List list;
private Lock lock;
public Consumer(List list, Lock lock) {
this.list = list;
this.lock = lock;
}
@Override
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
图片转存中…(img-ptSCfzWr-1710930930767)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-Er08JYcQ-1710930930767)]