Java – 线程执行顺序

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

Java - the thread execution order

问题

以下是翻译好的部分:

我正在尝试使用信号量(semaphore)严格按顺序启动10个线程。也就是说,在执行线程0后,应该执行线程1,但不是线程2。

但问题是,线程到达semaphore.acquire()方法的顺序是无序的,因此线程的执行顺序也是无序的。
如何在不使用thread.join()的情况下,通过信号量来解决这个问题呢?

public class Main {

    private Semaphore semaphore = new Semaphore(1, true);

    public static void main(String[] args) {
        new Main().start();
    }

    private void start() {
        for (int i = 0; i < 10; i++) {
            Runnable runnable = () -> {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("在 run 方法中:" + Thread.currentThread().getName());
                semaphore.release();
            };
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
    
}

输出:

在 run 方法中:Thread-0
在 run 方法中:Thread-1
在 run 方法中:Thread-4
在 run 方法中:Thread-5
在 run 方法中:Thread-3
在 run 方法中:Thread-2
在 run 方法中:Thread-6
在 run 方法中:Thread-7
在 run 方法中:Thread-9
在 run 方法中:Thread-8
英文:

I am trying to start 10 threads strictly in turn using a semaphore.
That is, after the execution of thread-0, thread-1 should be executed, but not thread-2.

But the problem is that the threads is arrives to the semaphore.acquire()-method in out of order, and therefore the execution of the threads is out of order.
How can I solve this problem with semaphore but without using thread.join()?

public class Main {

    private Semaphore semaphore = new Semaphore(1, true);

    public static void main(String[] args) {
        new Main().start();
    }

    private void start() {
        for (int i = 0; i &lt; 10; i++) {
            Runnable runnable = () -&gt; {
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(&quot;In run method &quot; + Thread.currentThread().getName());
                semaphore.release();
            };
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
    
}

Output:

In run method Thread-0
In run method Thread-1
In run method Thread-4
In run method Thread-5
In run method Thread-3
In run method Thread-2
In run method Thread-6
In run method Thread-7
In run method Thread-9
In run method Thread-8

</details>


# 答案1
**得分**: 2

你需要一个带有某种排序概念的同步对象。如果你熟悉美国的杂货店,可以考虑在熟食柜台上的“取号”设备,它告诉你轮到谁了。

代码草图:

```java
class SyncThing {
   int turn = 0; 
   synchronized void waitForTurn(int me) {
       while (turn != me)
           wait();
   }
   synchronized void nextTurn() {
        turn++;
        notifyAll();
   }
}

然后声明 SyncThing syncThing = new SyncThing();

并且以如下方式运行第 i 个线程:

Runnable runnable = () -> {
    syncThing.waitForTurn(i);
    System.out.println("In run method " + Thread.currentThread().getName());
    syncThing.nextTurn();
};

这是我凭记忆输入的,并不是完整的代码,但应该能够指导方向。

英文:

You need a synchronization object with some sort of concept of ordering. If you're familiar with US grocery stores, consider the "take a number" device at the deli counter that tells you whose turn it is.

Rough sketch of code:

class SyncThing {
   int turn = 0; 
   synchronized void waitForTurn(int me) {
       while (turn != me)
           wait();
   }
   synchronized void nextTurn() {
        turn++;
        notifyAll();
   }
}

then declare SyncThing syncThing = new SyncThing();

and run the i'th thread thus:

        Runnable runnable = () -&gt; {
            syncThing.waitForTurn(i);
            System.out.println(&quot;In run method &quot; + Thread.currentThread().getName());
            syncThing.nextTurn();
        };

This is typed in off the top of my head and is not offered as complete code, but it should show the way.

答案2

得分: 0

private void start() {
    final AtomicInteger counter = new AtomicInteger();

    for (int i = 0; i < 10; i++) {
        final int num = i;
        new Thread(() -> {
            while (counter.get() != num) {
            }
            System.out.println("在运行方法中 " + Thread.currentThread().getName());
            counter.incrementAndGet();
        }).start();
    }
}
英文:
private void start() {
    final AtomicInteger counter = new AtomicInteger();

    for (int i = 0; i &lt; 10; i++) {
        final int num = i;
        new Thread(() -&gt; {
            while (counter.get() != num) {
            }
            System.out.println(&quot;In run method &quot; + Thread.currentThread().getName());
            counter.incrementAndGet();
        }).start();
    }
}

huangapple
  • 本文由 发表于 2020年8月19日 03:11:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63475205.html
匿名

发表评论

匿名网友

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

确定