关于Semaphore中acquire方法的一个问题,信号量足够acquire了,但是线程不执行,我傻了……

下面是我的整个类,大家感兴趣可以把这段代码复制到ide中执行一下,我用的是jdk1.8。
是我在做leetcode的时候碰到的一个题:1114按序打印那个问题,然后我写了这么一段代码
因为想节约内存,所以想着只用一个Semaphore来解决,但是问题是第二个线程只需要2个通行证就可以执行,第一个线程执行完后还剩了2个通行证啊,但是第二个线程他就是卡在那了!

我大致解释下下面的代码吧:
1、Semaphore是java中的一个并发工具类(Doug Lea写的)
2、first,second,third方法的目的只是为了打印。这是leetcode留的打印入口不能删除,所以就留在了这里。
3、main方法中是我自己写的测试,大致就是按照leetcode中的题mu要求启动了三个线程后分别调用first,second,third方法
4、整道题的目的是为了按照顺序打印出first和second和third这三个字符串
有懂得的coder来支援下啊!!蒙了已经……
public class Foo {

private volatile Semaphore semaphore;

public Foo() {
    semaphore = new Semaphore(0);
}

public void first(Runnable printFirst) throws InterruptedException {
    // printFirst.run() outputs "first". Do not change or remove this line.
    System.out.println("需要0个许可证");
    printFirst.run();
    System.out.println("1执行");
    semaphore.release(2);
}

public void second(Runnable printSecond) throws InterruptedException {
    System.out.println("需要2个许可证");
    semaphore.acquire(2);
    // printSecond.run() outputs "second". Do not change or remove this line.
    printSecond.run();
    System.out.println("2执行");
    semaphore.release(3);
}

public void third(Runnable printThird) throws InterruptedException {
    System.out.println("需要3个许可证");
    semaphore.acquire(3);
    // printThird.run() outputs "third". Do not change or remove this line.
    printThird.run();
    System.out.println("3执行");
}

public static void main(String[] args) {
    Foo foo = new Foo();
    // 打印first的线程
    Thread first = new Thread(() -> {
        try {
            foo.first(() -> System.out.println("first"));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    first.setName("first");
    first.start();
    // 打印second的线程
    Thread second = new Thread(() -> {
        try {
            foo.second(() -> System.out.println("second"));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    second.setName("second");
    second.start();
    // 打印third的线程
    Thread third = new Thread(() -> {
        try {
            foo.third(() -> System.out.println("third"));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    third.setName("third");
    third.start();
    new Thread(()-> {
        while (true){
            System.out.println("可用许可证:"+foo.semaphore.availablePermits());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

}

是不是死锁了 Semaphore 是共享锁 线程third 不完成是不会让出锁

数据结构用错了,Semaphore只能限制并发,但是不能控制先后顺序

Foo类的代码发出来看看,有没有实现Runnable接口。

java我不熟悉,我感觉你信号没有用对。你third函数那边没有release,所以它占用了3个的时候second就没有了。

线程不执行 是指进行到哪一步不执行?

从你写的逻辑上来看,必须要控制first,second,third这个顺序,但是你写的main函数并不能保证一定是first先进入,second第二个进入,third第三个进入。如果first先进入了后释放了2个凭证,此时third进入了,程序就卡死了,中间加个thread.sleep(10)吧,保证一定是first,second,third这个顺序。其实你是无法保证哪条线程先执行,哪条线程在何时执行,完全由cpu来决定。当然大概率是first,second,third这个顺序