首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java - BlockingQueue冻结多线程应用

Java - BlockingQueue冻结多线程应用
EN

Stack Overflow用户
提问于 2020-04-08 04:16:10
回答 1查看 133关注 0票数 2

我正在制作一个包含两个线程的应用程序:一个线程向LinkedBlockingQueue写入值,另一个线程读取数据。我使用ScheduledExecutorService在一段时间内以秒为单位运行此操作。问题是我的应用程序在BlockingQueue的方法上冻结了,我不明白为什么。

这是一个常见的资源:

代码语言:javascript
复制
class Res{
    AtomicInteger atomicInteger = new AtomicInteger(0);
    BlockingQueue<String> q = new LinkedBlockingQueue<>();
}

这是阅读器

代码语言:javascript
复制
Semaphore semaphore = new Semaphore(1); /this is for reader does not take two places in thread pool
Runnable reader = ()->{
    try {
        semaphore.acquire();
        System.out.println(res.q.take()+" "+res.atomicInteger.incrementAndGet());
        semaphore.release();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};

作者:

代码语言:javascript
复制
Runnable writer = ()->{
    res.q.add("hi");
};

完整代码:

代码语言:javascript
复制
class Res{
    AtomicInteger atomicInteger = new AtomicInteger(0);
    BlockingQueue<String> q = new LinkedBlockingQueue<>();
}
public class Main {

    public static void main(String[] args) throws InterruptedException {

        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        Res res = new Res();
        Semaphore semaphore = new Semaphore(1); //this is for reader does not take two places in thread pool
        Runnable reader = ()->{
            try {
                semaphore.acquire();
                System.out.println(res.q.take()+" "+res.atomicInteger.incrementAndGet());
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable writer = ()->{
            res.q.add("hi");
        };
        Random rnd = new Random();

        for (int i = 0; i < 20; i++) {
            int time = rnd.nextInt(5)+ 2;
            executorService.schedule(writer,time, TimeUnit.SECONDS);
        }
        for (int i = 0; i < 20; i++) {
            int time = rnd.nextInt(5)+ 2;
            executorService.schedule(reader,time, TimeUnit.SECONDS);
        }

        executorService.shutdown();
}

它应该打印20行"hi number",但在某些行处冻结。例如,我当前的打印:

代码语言:javascript
复制
hi 1
hi 2
hi 3
hi 4
hi 5

我发现如果我增加线程数newScheduledThreadPool(20)它就会开始工作,但是我怎么才能让它有两个线程呢?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-08 04:48:58

要理解你的代码有点困难,尽管很明显正在发生的事情。由于使用了Executors.newScheduledThreadPool(2);,您最多只能同时运行两个线程。这两个线程都是reader线程。

因此,Thread-1进入了try块,并通过semaphore.acquire();获得了信号量许可,但队列是空的-因此它阻塞了res.q.take()。下一个线程- Thread-2也是一个读取器线程,但它不能获取permit,因为它已经被Thread-1占用并在semaphore.acquire();上被阻塞。由于您没有空间容纳其他线程(使用这两个线程时,您的池被阻塞),因此没有编写器会在您的队列中放入一些东西,从而取消阻塞Thread-1 (以便res.q.take()可以工作)。

添加更多的工作线程只会延迟问题--你可能会陷入和以前一样的境地。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61088676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档