我有多个线程在同一个队列中写入和读取。我正在使用ConcurrentLinkedQueue。任何线程都可以向队列添加元素,任何其他线程都可以轮询元素并对其进行处理。我的问题是如果队列是空的我想要在队列上轮询的线程要等到某个其他线程将某个元素添加到其中,并且如果所有线程都在等待,那么整个进程应该退出,这是没有线程正在写的。 我用它来列出目录及其子目录#faster scan。
中的所有文件以下是代码段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是正确的吗? 这适用于大型目录吗? EDIT1: 使用LinkedBlockingQueue,但是当所有线程都处于等待状态时,如何退出,这意味着没有更多的目录要扫描? 是否可以使用一个静态变量,增加它并检查它是否等于numberofthreads,然后退出。它有用还是有更好的解决方案?
编辑2: 谢谢你们。 退出线程由AtomicInteger解决。如果所有线程都在队列中等待,那么它们的AtomicInteger会递增,如果AtomicInteger等于线程数则会中断;
答案 0 :(得分: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(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,它的线程安全。你正在做的是实施阻止。有很多事情要解释如何做到这一点。你等待和通知的对象并不重要(尽管必须是同一个对象),同样的规则也适用。