当前位置: 首页 > 知识库问答 >
问题:

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

阎丰
2023-03-14

我有多个线程从同一队列中写入和读取。我正在使用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();
}
}
}

以上代码正确吗?它能一直满足我的需求吗。虽然程序运行良好,但我不理解线程是如何退出的,因为我没有提到任何退出条件。

使用同步是正确的吗?这也适用于大型目录吗?编辑1:使用LinkedBlockingQueue,但是当所有线程都处于等待状态时,这意味着没有更多的目录需要扫描时,如何退出?有一个静态变量,递增并检查它是否等于线程数,然后退出。这有效吗?或者有更好的解决方案吗?

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

共有1个答案

韦高格
2023-03-14

你所描述的是阻塞。你最好使用一个专门做这件事的数据结构,比如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

这使得你可以拥有消费者线程和生产者线程,你不必自己做任何锁定或同步。你只需使用“拿”()或“放”(项目),如果没有空间放那个项目或者没有项目可以拿,线程就会等待。它为你做相关的锁定和解锁。只有当它不能真正得到项目或把它放在那里时才会等待。还有一些操作会超时等等。

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

  • 您需要在一个线程中等待()并在另一个线程中通知()(我不知道代码中是否存在这种情况)
  • 需要在同一对象上同步的同步块中执行此操作。(正确)
  • 但是,您似乎没有实现任何其他要求。在等待之前,你需要检查队列是否为空,没有理由每次都等待是没有意义的
 类似资料:
  • 试图找出是否有人问过这个问题,但没有。 问题就在这里。以下必须通过Spring batch实现,有一个文件需要读取和处理。项读取器不是线程安全的。计划是让多线程同构处理器和多线程同构写入器通过单线程读取器读取项目。 有点像下面: 尝试了AsyncItemProcessor和AsyncItemWriter,但在处理器上保留调试点导致在释放该点(即单线程处理)之前不执行读取器。 任务执行程序已尝试如下

  • 本文向大家介绍Linux多线程编程快速入门,包括了Linux多线程编程快速入门的使用技巧和注意事项,需要的朋友参考一下 本文主要对Linux下的多线程进行一个入门的介绍,虽然是入门,但是十分详细,希望大家通过本文所述,对Linux多线程编程的概念有一定的了解。具体如下。 1 线程基本知识 进程是资源管理的基本单元,而线程是系统调度的基本单元,线程是操作系统能够进行调度运算的最小单位,它被包含在进程

  • 并发是什么?引用Rob Pike的经典描述: 并发是同一时间应对多件事情的能力 其实在我们身边就有很多并发的事情,比如一边上课,一边发短信;一边给小孩喂奶,一边看电视,只要你细心留意,就会发现许多类似的事。相应地,在软件的世界里,我们也会发现这样的事,比如一边写博客,一边听音乐;一边看网页,一边下载软件等等。显而易见这样会节约不少时间,干更多的事。然而一开始计算机系统并不能同时处理两件事,这明显满

  • 我应该设计一个组件,该组件应该通过在Java中使用多线程来实现以下任务,因为文件非常大/多,而且任务必须在很短的窗口内完成: 读取多个csv/xml文件并将所有数据保存在数据库中 读取数据库并将数据写入单独的csv文件 我对多线程很陌生 请告诉我您建议在Java或Spring Batch中使用传统的多线程。这里的输入源是多个的,输出源也是多个的。

  • Java 是最先支持多线程开发的语言之一, Java 多线程和并发也是 Java 学习的重点加难点。本教程根据作者多年 Java 开发经验总结而成,旨在帮助读者明白并发的原理。

  • 我正在开发一个应用程序(控制台),其中包含一个while循环,我希望允许用户暂停和恢复。经过一些研究,似乎一个额外的线程负责等待用户输入是正确的解决方案。 我已经能够实现持续等待输入的额外线程,并且还有一个kill方法,它设置flag变量来停止线程while()循环。不幸的是,除非有输入,否则while循环不会结束,只有在输入线程的while环至少完成一次后,这个kill标志才会生效。由于主线程也