【问题标题】:Java - the thread execution orderJava——线程执行顺序
【发布时间】:2020-08-19 06:41:23
【问题描述】:

我正在尝试使用信号量严格依次启动 10 个线程。 也就是说,在thread-0执行之后,应该执行thread-1,而不是thread-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("In run method " + Thread.currentThread().getName());
                semaphore.release();
            };
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
    
}

输出:

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

【问题讨论】:

  • 让线程按顺序运行,所有等待信号量的人都想知道为什么还要麻烦线程。但是,如果这只是一个练习,我认为您要么需要单独的信号量,要么在获取信号量后检查一个值以查看您是否是要运行的“下一个”线程,如果不是,则释放并重新获取。跨度>

标签: java multithreading semaphore


【解决方案1】:

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

代码粗略:

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();
        };

这是在我的脑海中输入的,并未作为完整的代码提供,但它应该显示方式。

【讨论】:

    【解决方案2】:
    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("In run method " + Thread.currentThread().getName());
                counter.incrementAndGet();
            }).start();
        }
    }
    

    【讨论】:

    • 是自旋锁,浪费CPU资源
    最近更新 更多