多线程写入和多线程读取的ConcurrentLinkedQueue并发问题#快速目录扫描



我有多个线程从同一队列中进行写入和读取。我正在使用ConcurrentLinkedQueue。任何线程都可以向队列中添加元素,任何其他线程都可以轮询元素并对其进行处理。我的问题是,如果队列为空,我希望在队列上轮询的线程等待,直到其他线程将某个元素添加到队列中,如果所有线程都在等待,则整个进程应该退出,即不再有线程在写入。我使用它来列出目录及其子目录中的所有文件#更快扫描。

以下是代码片段1:

private Queue dList=new ConcurrentLinkedQueue();

/*一些处理代码*/

public void Run
{
/* some processing code */
while(dName == null)
{
try{
synchronized(dList){
dList.wait();
}
} catch(InterruptedException e){}
dName = dList.poll();
}
/* some processing code */
{
dList.add(item);
synchronized(dList){
dList.notifyAll();
}
}
}

以上代码正确吗?它总是做我想做的事吗。虽然程序运行良好,但我不明白线程是如何退出的,因为我并没有提到任何退出条件。

在ConcurrentLinkedQueue上使用synchronized是否正确?这也适用于巨大的目录吗?第1版:使用LinkedBlockingQueue,但是当所有线程都处于等待状态时,意味着没有更多的目录要扫描时,如何退出?如果有一个静态变量,它能工作吗?递增它并检查它是否等于读取数,然后退出。它有效吗?或者有更好的解决方案吗?

编辑2:谢谢大家。从线程退出由AtomicInteger解决。若所有线程都在队列上等待,则它们的AtomicInteger递增,若AtomicInteger等于线程数,则中断;

您所描述的是阻塞。您最好使用像ArrayBlockingQueue这样专门做这件事的数据结构,而不是自己的数据结构。它有并发性,但也有访问队列的阻塞方式,迫使运行的线程等待,直到有项目要获取。使用所有必需的锁定等。您也可以使用LinkedBlockingQueue进行无限制的操作

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.htmlhttps://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html

这使得您可以拥有使用者线程和生产者线程,而不必自己进行任何锁定或同步。你只需要使用take()或执行put(item),如果没有空间放置该项目或没有项目可拿,线程就会等待。它为您进行相关的锁定和解锁。只有当它无法真正拿到或放在那里时才会等待。还有一些操作会超时等。

new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) return;
try {
File file = blockingqueue.take();
} catch (InterruptedException ignored) {
return;
}
processFile(file);
}
}
}).start();

您实际上不必同步ConcurrentLinkedQueue,它是线程安全的。你正在做的是实现阻塞。有很多事情可以解释应该如何做到这一点。无论您等待并通知哪个对象(尽管必须是同一个对象),都适用相同的规则。

  • 你需要在一个线程中等待(),在另一个线程里通知()(我不能告诉您的代码中是否存在这种情况)
  • 您需要在同一对象上同步的同步块中执行此操作。(正确)
  • 但是,您似乎没有实现任何其他要求。在等待之前,您需要检查队列是否为空,没有必要每次都无故等待

最新更新