gpt4 book ai didi

java - 为什么不能用 AtomicBoolean 标志中断可运行的任务?

转载 作者:行者123 更新时间:2023-11-29 07:25:07 26 4
gpt4 key购买 nike

我有下一个任务

public class QuittableTask implements Runnable {
final int id;

public QuittableTask(int id) {
this.id = id;
}

private AtomicBoolean running = new AtomicBoolean(true);

public void quit() {
System.out.println("Quite " + Thread.currentThread().getName());
running.set(false);
}

@Override
public void run() {
while (running.get()) {
System.out.println(Thread.currentThread().getName());
new Nap(0.1);
}
System.out.print(id + " ");
}

我运行了很多任务使用

public class QuittingTasks {
public static final int COUNT = 1500;

public static void main(String[] args) throws InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
List<QuittableTask> tasks =
IntStream.range(1, COUNT)
.mapToObj(QuittableTask::new)
.peek(es::execute)
.collect(Collectors.toList());
Thread.currentThread().sleep(1000);
tasks.forEach(QuittableTask::quit);
es.shutdown();
}

当我使用 COUNT < 10000 时一切正常。所有线程都被终止。程序在 2 秒内完成。

但是当我使用 COUNT > 100001 方法时,相当 无法到达,我的程序进入无限循环。我不明白这样的行为。有人可以给我解释一下吗?

最佳答案

如果您仔细查看日志(在您的代码中添加一些日志),您会发现当程序生成 OutOfMemoryError 时。错误如下所示:

java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:957)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1378)
at java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:372)
at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.java8.demo.Main.main(Main.java:58)

这意味着当您尝试对所有任务调用 quit 时,您将获得 OutOfMemory,但由于错误发生,它永远不会被执行,因为您的 boolean 标志从未设置为 false。其他线程继续运行。

您会注意到内存不足是因为 VM 无法创建 native 线程。现在您正在使用 Executors.newCachedThreadPool();。因此您的线程池最大大小可以是 Integer.MAX_VALUE 但在达到该值之前您的 VM 无法创建新线程。我已将执行程序更改为 FixTheradPool,如 ExecutorService es = Executors.newFixedThreadPool(8);。它适用于较高的 COUNT 值,因为它只会创建 8 个线程。

我已经放置了一个 try-catch block 来跟踪异常,如下所示。此外,我通过调用 System#exit 强制退出 VM 来跟踪控制台上的日志。

try {
ExecutorService es = Executors.newCachedThreadPool();
List<QuittableTask> tasks = IntStream.range(1, COUNT).mapToObj(QuittableTask::new).peek(es::execute)
.collect(Collectors.toList());
Thread.currentThread().sleep(1000);
tasks.forEach(QuittableTask::quit);
es.shutdown();
} catch (Throwable e) {
System.out.println("Error" + e.getMessage());
e.printStackTrace();
System.exit(0);
}

关于java - 为什么不能用 AtomicBoolean 标志中断可运行的任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54724508/

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