为了账号安全,请及时绑定邮箱和手机立即绑定

如何利用 Java 多线程来获得最大速度和最小错误?

如何利用 Java 多线程来获得最大速度和最小错误?

回首忆惘然 2023-07-28 15:59:16
我正在做作业,并且在利用线程使程序尽可能快地运行方面遇到了麻烦。该作业是关于生成大量随机自回避游走(SAW)的。分配指南表示执行 1,000 个并发运行的线程,从而尽可能节省时间。每个线程内都存在一个嵌套的 for 循环。对于 n = 10 到 n = 40,程序生成 N_w 次行走。我的目标是使 N_w 尽可能大并产生更多的步行。我已经创建了 1,000 个线程,但我不确定是否正确利用它们来尽可能快地进行计算。SawGenerator 是一个扩展 Thread 的类,并包含一个嵌套的 for 循环来生成所有的遍历。我尝试通过创建 1,000 个 SawGenerators 并逐个启动它们来生成 1,000 个线程,并将每个 SawGenerator 中的 N_w 设置为 500。for (int i = 0; i < 1000; i++) {        SawGenerator mySawGenerator = new SawGenerator();        mySawGenerator.start();}for (Map.Entry<Integer, Double> entry : numSuccessfulWalks.entrySet()) {        int curLength = entry.getKey();        System.out.println("SAW's of length:  " + curLength);        System.out.println("    numSuccessfulWalks(" + curLength + "): " + numSuccessfulWalks.get(curLength));        System.out.println("    <Rn^2>: " + totalEndSqDist.get(curLength)/numSuccessfulWalks.get(curLength));        System.out.println("    Fraction Perimeter: " + numSuccessfulWalks.get(curLength)/(1000*500));    }long endTime = System.currentTimeMillis();System.out.println("Total Runtime in Seconds: " + ((endTime-startTime) / 1000));然而,这给了我几个不同的结果:1) 我的程序经常会因 ConcurrentModificationException 崩溃。我相信这是因为我的线程涉及到哈希图的插入,并且错误是多个线程试图同时更改同一个哈希图的结果。2)“以秒为单位的总运行时间”,又名我的代码的最后一行,将在没有我也想在其之前打印的地图信息的情况下打印。不会有错误输出,我不确定是什么原因导致出现这种结果。3)我的程序将运行并完成所有计算,没有任何问题。我认为这只发生在线程表现“理想”时。然后,我在启动每个线程后添加了 join() 方法,这导致我的程序运行速度有点慢,但毫无疑问,它更加一致。我相信这是因为 join() 方法在开始下一个线程之前等待每个线程完成。for (int i = 0; i < 1000; i++) {        SawGenerator mySawGenerator = new SawGenerator();        mySawGenerator.start();        try {            mySawGenerator.join();        } catch (InterruptedException e) {            e.printStackTrace();        }}现在,当我试图加快程序速度时,我感觉自己陷入了僵局。在每个线程启动后不使用 join() 会更快,因为它允许并行运行计算。但是,它可能会导致诸如 ConcurrentModificationException 之类的错误。在我发现的第二个结果中,我得到了一个意想不到的结果,我的一些代码根本没有执行。所以,我现在有两个问题:1) 当我不加入我的线程时,我发现的结果中的#2 发生了什么?为什么我的代码的整个部分“跳过”执行?但更重要的是:2)如何正确使用线程,使其在运行时不会出现任何错误?我可以在每个线程启动后加入它们,但这意味着没有一个线程可以同时运行,不是吗?如果我这样做,我还不如不使用线程。任何帮助,将不胜感激!提前致谢。:)
查看完整描述

1 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

这是一个非常广泛的问题,我不确定它是否非常适合这种格式,但无论如何我都会尽力回答你。

当我不加入我的帖子时,我发现的第 2 个结果发生了什么?为什么我的代码的整个部分“跳过”执行?

当您启动一个线程时,它将在后台执行其代码,但启动本身返回得相当快。当您加入一个线程时,您会暂停自己的执行,直到正在加入的线程完成。如果没有加入,您实际上是在最终循环中“按原样”对执行结果进行采样,而此时许多线程可能仍在运行。因此,您会丢失这些结果。

2)如何正确使用线程,使其在运行时不会出现任何错误?我可以在每个线程启动后加入它们,但这意味着没有一个线程可以同时运行,不是吗?如果我这样做,我还不如不使用线程。

这是一个宽泛的问题,但我可以强调一些要点:

  • 使用的线程数不要超过可用于 CPU 密集型任务的 CPU 线程数

  • 最大限度地减少共享资源的并发修改。所有这些线程真的需要修改 Hashmap 吗?

  • 查看生产者/消费者设计。您可以有许多线程生成随机游走,而只有一个线程收集完成的游走。


查看完整回答
反对 回复 2023-07-28
  • 1 回答
  • 0 关注
  • 80 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信