使用信号量

Using a semaphore

我想知道如何让这些线程一个接一个地工作,以及如何让第一个线程总是 运行 在第二个线程之后。我创建了一个信号量,但我不确定如何使用它。

public class A extends Thread {
    private int i;
    public A(int x) {
        i = x;
    }@
    Override
    public void run() {
        System.out.println(i);
    }
}

/** 主要内容 **/

A c1 = new A(5);
A c2 = new A(6);
Semaphore s = new Semaphore(1, true);
c1.start();
c2.start();

new Thread(new Runnable() {
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {}
            System.out.println("+");
        }
    }
}).start();

new Thread(new Runnable() {
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(70);
            } catch (InterruptedException e) {}
            System.out.println("*");
        }

    }
}).start();

您可以将信号量中的许可建模为:"allowed to run"。

由于您希望第一个线程被允许自动 运行,您不能对第一个线程使用 acquire,因为它会与第二个线程竞争许可。所以第一个线程启动,假设它有许可。当第一个线程完成时,它 release-es 许可。第二个线程需要 acquire 许可才能开始工作。

首先创建一个具有零许可的信号量(因为第一个线程已经隐式拥有一个许可)

final Semaphore s = new Semaphore(0, true);

第一个线程的最后一行应为:

s.release();

(请注意,它允许在没有获取的情况下发布 - 信号量只是重要的,它不会跟踪谁拥有哪个许可)

第二个话题的第一行应该是:

s.acquireUninterruptibly();

(或者只是 acquire() 但是你需要赶上 InterruptedException

  • I would like to know how can i make those threads work one after the other, and
  • how to make the first one always run after the second one. I created a semaphore, but i not sure about how to use it.

如果您希望线程在调用线程 c2 之前完成,您可以在您的情况下使用 join()。像这样(线程在 main 的线程中调用):

c1.start(); // Start thread `c1` first
c1.join();  // `main` now waits for `c1` to finish
c2.start(); // Start thread `c2` next
c2.join();  // `main` now waits for `c2` to finish

这应该可以回答您的问题。

我对信号量略知一二。

一般来说,您不能使用信号量来控制线程的执行顺序。信号量是一个或多个资源的锁。想要访问资源的线程相互竞争,您无法控制信号量接下来将访问权授予谁。

我知道另一个答案中的 "trick"。我没有测试它,它可能会起作用,但我认为这不是正确的方法。

这是一个没有信号量的例子:

import java.util.concurrent.Semaphore;

class A extends Thread {

    private int i;
    public A(int x) {
        i = x;
    }

    public void run() {
       System.out.println(i);
    }

    public static void main(String[] args) throws Exception {
        A thread1 = new A(5);
        A thread2 = new A(6);
        thread1.start();
        thread1.join();
        thread2.start();
        thread2.join();
    }
}

如果你想使用信号量(虽然我不明白为什么)那么这个例子可能是这样的:

import java.util.concurrent.Semaphore;

class A extends Thread {

        private int i;
        final static Semaphore semaphore = new Semaphore(1, true);

        public A(int x) {
            i = x;
        }

        public void run() {
            try {

                /*thread stops here until it gets permit to go on*/
                semaphore.acquire();
                System.out.println(i);
            /*exception must be caught or thrown*/
            } catch (InterruptedException e) { }

            //CRITICAL SECTION

            semaphore.release();

        }

    public static void main(String[] args) throws Exception {
        A thread1 = new A(5);
        A thread2 = new A(6);
        thread1.start();
        thread1.join();
        thread2.start();
        thread2.join();
    }
}

虽然你的问题可以通过线程的 'join' 特性来解决 可以在开始下一个 asi 之前强制完成一个线程(如中所示) Elyasian 的例子,但仍然必须补充一点,你是在正确的轨道上 就采取的信号量路线而言。

信号量 s = 新信号量(1, true);

在此语句中,设置为 'true' 的第二个参数称为公平设置。

换句话说,在我们的场景中,这确保了(FIFO - 先进先出)"First come First serve" ....

即首先调用 acquire 的线程将获得许可并完成 它的任务首先,然后第二个线程才能继续 它的执行。

所以你原来的问题.....即

我想知道如何使这些线程一个接一个地工作,以及如何使第一个线程始终运行 在第二个线程之后

可以改写为

我想知道如何确保调用 acquire 的线程 首先在信号量上到达 运行 首先总是....