循环中线程的不同结果,它们在Java中的工作方式如何?

huangapple go评论127阅读模式
英文:

Different result of Thread in loop,how they work in java?

问题

当我在一个for循环中创建多个线程时,根据不同的方法,结果会有所不同。

如果我更改doS()方法如下:

private List<Future<Integer>> futureList = new ArrayList<>();
@Test
void testThread() throws ExecutionException, InterruptedException {
    ExecutorService executorService = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100 * 1024));
    for (int i = 0; i < 10000; i++) {
        int finalI = i;
        Future<Integer> future = executorService.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println("call ==" + finalI);
                return finalI;
            }
        });
        doS(future);
        System.out.println("for end ==" + finalI);
    }
    System.out.println("---------====------------");
    executorService.shutdown();
}

private void doS(Future<Integer> future) throws ExecutionException, InterruptedException {
    Integer integer = future.get();
}

结果会变成这样:

call ==0
for end ==:0
call ==1
for end ==:1
call ==2
for end ==:2
call ==3
for end ==:3
call ==4
for end ==:4
call ==5
for end ==:5
call ==6
for end ==:6

doS()方法不属于executorService,它不是一个线程方法,所以为什么循环会以不同的方式工作?为什么它们以不同的方式工作?

谢谢。

英文:

When i create many threads in a for loop,if i take diffierent method,there are diffierent result.

    private List&lt;Future&lt;Integer&gt;&gt; futureList = new ArrayList&lt;&gt;();
    void testThread() throws ExecutionException, InterruptedException {
    ExecutorService executorService = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue&lt;&gt;(100 * 1024));
    for (int i = 0; i &lt; 10000; i++) {
            int finalI = i;
            Future&lt;Integer&gt; future = executorService.submit(new Callable&lt;Integer&gt;() {
                @Override
                public Integer call() throws Exception {
                    System.out.println(&quot;call ==&quot; + finalI);
                    return finalI;
                }
            });
            doS(future);
            System.out.println(&quot;for end ==:&quot;+finalI);
        }
        System.out.println(&quot;---------====------------&quot;);
        executorService.shutdown();
    }

    private void doS(Future&lt;Integer&gt; future) throws ExecutionException, InterruptedException {
        this.futureList.add(future);
    }

the result like this:

for end ==:0
for end ==:1
for end ==:2
call ==0
for end ==:3
call ==1
for end ==:4
call ==4
call ==2
call ==5
call ==3
for end ==:5
for end ==:6

However,if i change the method doS():

    private List&lt;Future&lt;Integer&gt;&gt; futureList = new ArrayList&lt;&gt;();
    @Test
    void testThread() throws ExecutionException, InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue&lt;&gt;(100 * 1024));
        for (int i = 0; i &lt; 10000; i++) {
            int finalI = i;
            Future&lt;Integer&gt; future = executorService.submit(new Callable&lt;Integer&gt;() {
                @Override
                public Integer call() throws Exception {
                    System.out.println(&quot;call ==&quot; + finalI);
                    return finalI;
                }
            });
            doS(future);
            System.out.println(&quot;for end ==:&quot;+finalI);
        }
        System.out.println(&quot;---------====------------&quot;);
        executorService.shutdown();
    }

    private void doS(Future&lt;Integer&gt; future) throws ExecutionException, InterruptedException {
        Integer integer = future.get();
    }

the result changed:

call ==0
for end ==:0
call ==1
for end ==:1
call ==2
for end ==:2
call ==3
for end ==:3
call ==4
for end ==:4
call ==5
for end ==:5
call ==6
for end ==:6

the method of 'doS()' is not belongs to 'executorService',is not a thread menthod,so is the loop will work in order?why they worked in diffierent ways?
Thank you.

答案1

得分: 1

get(future)函数会导致调用它的线程等待 future 完成并返回结果。因此,它将你的多线程代码转变成一个循环,该循环会启动一个线程,然后等待它完成后再启动下一个线程。这几乎完全消除了使用线程的意义。

你的原始版本没有等待,因此所有线程都被创建,并且将按照操作系统决定的顺序启动。

如果你需要按特定顺序执行操作,请不要使用线程。你无法强制执行特定顺序。如果你想知道为什么第一个版本以随机顺序发生——那是因为操作系统安排线程,并在它认为最佳的时候在它们之间切换,而且没有办法进行排序。它们可能会顺序执行,也可能会在不同的核心/处理器上同时执行,或者以任意随机顺序执行。这是使需要协调线程的多线程变得困难的因素之一。

英文:

The get(future) function causes the thread its called on to wait for the future to finish and return the result. So its turning your multithreaded code into a loop that starts a thread, then waits for it to finish before starting the next thread. Which pretty much eliminates the point of using a thread at all.

Your original version doesn't have a wait, so all the threads are spawned, and will be launched in whatever order the OS decides.

If you need things to happen in a particular order- don't use threads. You can't enforce that. If you're wondering why the first version is happening in random order- its because the OS schedules threads and switches between them whenever it decides is best, and there's no way to order it. They may happen sequentially, or at the same time in different cores/processors, or in any random order. That's one of the things that makes multithreading where threads need to coordinate hard.

huangapple
  • 本文由 发表于 2020年10月4日 16:26:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/64192556.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定