有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有多线程写入和多线程读取的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) 个答案

  1. # 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(项目),如果没有空间放置该项目或没有项目可执行,线程将等待。它会为您执行相关的锁定和解锁。只有当它无法真正获取或放置物品时才会等待。还有一些操作会超时等

        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,它是线程安全的。你所做的是实现阻塞。有很多事情可以解释如何做到这一点。不管你在哪个对象上等待和通知(尽管必须是同一个对象),都适用相同的规则

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