带有多线程写入和多线程读取的ConcurrentLinkedQueue的java并发问题#快速目录扫描
我有多个线程从同一队列中写入和读取。我正在使用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,但是当所有线程都处于等待状态,这意味着没有更多的目录要扫描时,如何退出? 如果有一个静态变量,它会工作吗?增加它并检查它是否等于numberofthreads,然后退出。它有效吗?或者有更好的解决方案吗
编辑2: 谢谢大家。 从线程退出由AtomicInteger解决。如果所有线程都在队列中等待,那么它们的AtomicInteger将递增,如果AtomicInteger等于线程数,则中断
# 1 楼答案
你所描述的是阻塞。你最好使用一个专门做这件事的数据结构,比如
ArrayBlockingQueue
,而不是你自己的数据结构。它有并发性,但也有阻塞方式来访问队列,这迫使运行的线程等待,直到有一个要获取的项目。通过所有必需的锁定等功能,您还可以使用LinkedBlockingQueue
执行无限的操作https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.html https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html
这使得您可以拥有消费线程和生产者线程,而不必自己进行任何锁定或同步。只需使用take()或执行put(项目),如果没有空间放置该项目或没有项目可执行,线程将等待。它会为您执行相关的锁定和解锁。只有当它无法真正获取或放置物品时才会等待。还有一些操作会超时等
您实际上不必同步ConcurrentLinkedQueue,它是线程安全的。你所做的是实现阻塞。有很多事情可以解释如何做到这一点。不管你在哪个对象上等待和通知(尽管必须是同一个对象),都适用相同的规则