gpt4 book ai didi

java - 协调两个线程时的并发问题

转载 作者:行者123 更新时间:2023-12-03 12:53:52 32 4
gpt4 key购买 nike

我试图将循环的工作分为两个线程。
我正在使用ExecutorService创建第二个线程,而将主线程用作另一个线程。
我正在使用计数器在达到某个值时停止循环,但是我无法在这两个线程之间同步计数器,并且循环额外运行了一个时间。
另外,我在主线程中使用while循环来知道何时达到所需的计数来打印结束时间,这也不起作用。

ExecutorService executorService = Executors.newFixedThreadPool(1);

Clock clock = new Clock();

int count = 5;
AtomicInteger c = new AtomicInteger(1);
clock.start();

executorService.execute(()->{
while (c.get() <= count) {

System.out.println("LOOP ONE" + "----PRINT_ME");
c.incrementAndGet();
}
});

while (c.get() <= count) {

System.out.println("LOOP TWO" + "----PRINT_ME");
c.incrementAndGet();
}

while(true) {
if(c.get() == count) {
System.out.println("STOPPED");
clock.stop();
break;
}
}
输出 -
Clock started at -- 2020-07-25T12:32:59.267
LOOP TWO----PRINT_ME
LOOP TWO----PRINT_ME
LOOP TWO----PRINT_ME
LOOP TWO----PRINT_ME
LOOP TWO----PRINT_ME
LOOP ONE----PRINT_ME
在上面的代码中PRINT_ME应该只被打印5次(int count = 5;),但是被打印6次(额外一次)。
我不确定这是怎么回事,以及我们如何在两个线程之间共享一个计数。
PSI:如果我添加Thread.sleep(2000);在两个循环中
executorService.execute(()->{
while (c.get() <= count) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("LOOP ONE" + "----PRINT_ME");
c.incrementAndGet();
}
});

while (c.get() <= count) {

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("LOOP TWO" + "----PRINT_ME");
c.incrementAndGet();
}
输出为:
Clock started at -- 2020-07-25T12:54:15.596
LOOP TWO----PRINT_ME
LOOP ONE----PRINT_ME
LOOP TWO----PRINT_ME
LOOP ONE----PRINT_ME
LOOP TWO----PRINT_ME
LOOP ONE----PRINT_ME

最佳答案

问题是您先轮询计数器,执行一个操作,然后递增计数器以表明作业已完成。
这将创建一个窗口,两个线程可以同时执行工作,并在完成后执行增量操作,这为时已晚。
为了使可视化更容易,让我们假设所需的计数为1,并且有两个线程在争夺要执行的任务。在您的实现中,两个线程都将首先检查对两个都适用的c.get() <= count,然后执行导致您所描述的问题的任务。
为了防止这种情况,线程需要首先声明一个“空闲插槽”,然后才执行该任务。这可以通过在作业开始之前增加计数器,然后在开始每个作业之前验证最大计数条件来执行:

    int count = 5;
AtomicInteger c = new AtomicInteger(0);

executorService.execute(()->{
while (c.incrementAndGet() <= count) {
// ...
});

while (c.incrementAndGet() <= count) {
// ..
}

关于java - 协调两个线程时的并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63085401/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com