Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
初学者Java多线程问题_Java_Multithreading - Fatal编程技术网

初学者Java多线程问题

初学者Java多线程问题,java,multithreading,Java,Multithreading,我正在制作的Java多线程文件爬虫有问题。我的问题是,我有一个工作队列,它是一个linkedBlockingQueue,包含我想用线程爬过的文件名,每个线程将从工作队列中获取(),在扫描文件时,它可能将另一个文件名放入工作队列(这是一个依赖项检查器程序)。因此,当所有线程试图从(最终)空的工作队列中take()时,我永远无法确定工作何时全部完成,所有线程最终将进入等待状态 所以我想我的问题是,一旦所有的工作都完成了(当所有的线程都进入等待状态时),是否有一种有效的方法来终止所有的线程?目前我只在

我正在制作的Java多线程文件爬虫有问题。我的问题是,我有一个工作队列,它是一个linkedBlockingQueue,包含我想用线程爬过的文件名,每个线程将
从工作队列中获取()
,在扫描文件时,它可能
将另一个文件名放入工作队列(这是一个依赖项检查器程序)。因此,当所有线程试图从(最终)空的工作队列中
take()
时,我永远无法确定工作何时全部完成,所有线程最终将进入等待状态

所以我想我的问题是,一旦所有的工作都完成了(当所有的线程都进入等待状态时),是否有一种有效的方法来终止所有的线程?目前我只在主线程上使用
sleep()
,然后在所有工作线程上使用
interrupt()


如果这个问题听起来很困惑,很抱歉。

您可以使用下面的方法。如果需要,可以添加观察者模式。 或者简单地说——收集等待线程的列表,然后中断它们,而不是用死亡数据包发送信号

公共类访问计数LinkedPrioQueue{
private final LinkedBlockingQueue mWrappingQueue=新LinkedBlockingQueue();
私有最终对象mSyncLockObj=新对象();
私有final int mMaxBlockingThreads;
私人最终mDeathSignallingObject;
私有易失性int-mNumberOfThreadsInAccessLoop=0;
public AccessCountingLinkedPrioQueue(最终int-pMaxBlockingThreads,最终T-pDeathSignallingObject){
mMaxBlockingThreads=pMaxBlockingThreads;
mDeathSignallingObject=pDeathSignallingObject;
}
public T take()抛出InterruptedException{
最后一次回顾;
已同步(mSyncLockObj){
++mnnumberofthreadsinaccessloop;
}
已同步(mWrappingQueue){
if(mNumberOfThreadsInAccessLoop>=mMaxBlockingThreads&&mWrappingQueue.isEmpty())表示死亡();
retVal=mWrappingQueue.take();
}
已同步(mSyncLockObj){
--mnnumberofthreadsinaccessloop;
}
返回返回;
}
私人死亡{
对于(int i=0;i
我以前遇到过这个问题,我找到的唯一方法是向
阻塞队列发送一个特殊的标记对象。当队列
.take()
处理对象时,如果这是标记,则
线程将结束自身


我尝试过其他解决方案,比如唤醒线程并检测异常,但没有成功。

有一种模式称为。基本上,当生产者完成时,在队列中插入一个特殊值,通知消费者停止。您可以为每个消费者插入一颗药丸,或者,一旦消费者获得毒药药丸,将其返回到下一个消费者的队列中。因为听起来你只是在排队,比如

public static final String POISON_PILL = "DONE";
或者在Java8中,使用
Optional
来包装您的值,然后就不存在避孕药了

BlockingQueue<Optional<...>> queue;
阻塞队列;
另一个选项是使用
ExecutorService
(它实际上由
阻塞队列
支持)并将每个文件作为自己的任务提交,然后在完成后使用
ExecutorService.shutdown()
。这样做的问题是,它将代码连接得比需要的更紧密,并且使重用数据库和HTTP连接等资源变得更加困难


我会避免打断您的员工向他们发出信号,因为这可能会导致阻塞IO操作失败。

thanx表示反对票。但是,以上帝的名义,请留下一条评论,为什么这是不好的,所以我们都知道了。不确定是否有否决票,但我会用ExecutorService来管理线程。
BlockingQueue<Optional<...>> queue;