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

我正在做作业,并且在利用线程使程序尽可能快地运行方面遇到了麻烦。该作业是关于生成大量随机自回避游走(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)如何正确使用线程,使其在运行时不会出现任何错误?我可以在每个线程启动后加入它们,但这意味着没有一个线程可以同时运行,不是吗?如果我这样做,我还不如不使用线程。


任何帮助,将不胜感激!提前致谢。:)


回首忆惘然
浏览 81回答 1
1回答

繁星coding

这是一个非常广泛的问题,我不确定它是否非常适合这种格式,但无论如何我都会尽力回答你。当我不加入我的帖子时,我发现的第 2 个结果发生了什么?为什么我的代码的整个部分“跳过”执行?当您启动一个线程时,它将在后台执行其代码,但启动本身返回得相当快。当您加入一个线程时,您会暂停自己的执行,直到正在加入的线程完成。如果没有加入,您实际上是在最终循环中“按原样”对执行结果进行采样,而此时许多线程可能仍在运行。因此,您会丢失这些结果。2)如何正确使用线程,使其在运行时不会出现任何错误?我可以在每个线程启动后加入它们,但这意味着没有一个线程可以同时运行,不是吗?如果我这样做,我还不如不使用线程。这是一个宽泛的问题,但我可以强调一些要点:使用的线程数不要超过可用于 CPU 密集型任务的 CPU 线程数最大限度地减少共享资源的并发修改。所有这些线程真的需要修改 Hashmap 吗?查看生产者/消费者设计。您可以有许多线程生成随机游走,而只有一个线程收集完成的游走。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java