gpt4 book ai didi

java - 生产者消费者模式: on demand thread

转载 作者:行者123 更新时间:2023-12-02 06:50:42 25 4
gpt4 key购买 nike

考虑下面的类:

public class TaskWorkDemo {
private final Object mLock = new Object();
private final ArrayDeque<String> mQueue = new ArrayDeque<String>();
private Thread mThread;

private String getOne(){
synchronized (mLock){
return mQueue.isEmpty() ? null : mQueue.peek();
}
}

//--produce--
private void putOne(String s){
synchronized (mLock){
mQueue.offer(s);
}

//-- at time T --
if(mThread == null || !mThread.isAlive()){
mThread = new Thread(new Runner());
mThread.start();
}
}

private class Runner implements Runnable{

//--consume--
@Override
public void run() {
String s = getOne();

while (s != null){
System.out.println(s);
s = getOne();
}

//-- at time T --
mThread = null;
}
}
}

仅当队列中有挂起的字符串时,消费者线程才应该存在,即不像我们看到的典型用法那样在队列上等待。因此,我尝试在每次将某些内容添加到队列时创建一个线程,方法是检查任何先前的线程是否不存在或已完成。

但是这种方法有一个极端情况(参见上面代码中的 //-- 在时间 T --):消费者线程脱离了循环,但尚未完成。生产者线程将要检查之前的消费者线程是否还在,它会发现它仍然正在完成,并跳过创建一个新的线程。

有什么想法吗?

最佳答案

您不应将 mThread 设置为 null,因为它最终会导致 NullPointerException:

  1. thread1 检查mThread == null,返回 false
  2. thread2 设置mThread = null
  3. thread1 检查 !mThread.isAlive(),这会抛出 NullPointerException

您可能应该使用 ThreadPoolExecutor 来解决您的问题,正如 kan 在他的回答中建议的那样,但如果由于某种原因您不能/不会这样做,那么您可以替换您的

if(mThread == null || !mThread.isAlive())

条件为

while(mThread.isAlive()) {
sleep(sleep_parameter);
}
// mThread is no longer alive
mThread = new Thread(new Runner());
mThread.start();

loop,将循环直到线程终止。比 sleep 更有效的替代方案是使用诸如信号量之类的东西,以便消费者可以在其线程即将终止时发出信号(生产者传递零许可的信号量)消费者然后在信号量上调用 acquire ,导致其阻塞;然后消费者在即将终止时在信号量上调用 release ,这会唤醒生产者)

关于java - 生产者消费者模式: on demand thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18065754/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com