Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 困惑于;“按顺序打印”;LeetCode问题_Java_Multithreading_Runnable - Fatal编程技术网

Java 困惑于;“按顺序打印”;LeetCode问题

Java 困惑于;“按顺序打印”;LeetCode问题,java,multithreading,runnable,Java,Multithreading,Runnable,这应该是多线程上的一个简单问题: “同一个Foo实例将被传递给三个不同的线程。线程A将调用first(),线程B将调用second(),线程C将调用third()。设计一个机制并修改程序,以确保second()在first()之后执行,third()在second()之后执行。”他们给出以下代码: public Foo() {} public void first(Runnable printFirst) throws InterruptedException { //

这应该是多线程上的一个简单问题: “同一个Foo实例将被传递给三个不同的线程。线程A将调用first(),线程B将调用second(),线程C将调用third()。设计一个机制并修改程序,以确保second()在first()之后执行,third()在second()之后执行。”他们给出以下代码:

public Foo() {}
    public void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
    }
    public void second(Runnable printSecond) throws InterruptedException {
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
    }
    public void third(Runnable printThird) throws InterruptedException {
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
**似乎我可以使用下面的Thread.join来解决这个问题,但我不明白的是,为什么他们会将Runnable的实例传递给每个方法,以及如何正确地进行传递,因为下面的代码会将每个消息打印两次——一次是因为Thread.start()会调用相应的run()方法,另一次是因为Thread.start()会直接调用该方法。我知道这是一种错误的方法,但如果我们尝试使用join方法,就无法找出正确的解决方案**

public Foo() throws InterruptedException {
        Runnable r1 = () -> {
            System.out.println("first ");
        };
        first(r1);
        
        Runnable r2 = () -> {
            System.out.println("second ");
        };
        second(r2);
        
        Runnable r3 = () -> {
            System.out.println("third ");
        };
        third(r3);
        
        Thread t1 = new Thread(r1);
        t1.start();
        try {
            t1.join(); // wait for this thread to finish before starting #2
        }
        catch(Exception e) {
            System.err.println("Thread 1 error");
        }
        
        Thread t2 = new Thread(r2);
        t2.start();
        
        try {
            t2.join();
        }
        catch(Exception e) {
            System.err.println("Thread 2 error");
        }
        
        Thread t3 = new Thread(r3);
        t3.start();
        
        try {
            t3.join();
        }
        catch(Exception e) {
            System.err.println("Thread 3 error");
        }
    }```

Leetcode是针对代码挑战的,所以我们不应该给出完整的解决方案,因为这对您来说不是一个挑战

所以这里有一个提示:使用两个对象,一个通知方法
second()
方法
first()
完成,另一个通知方法
third()
方法
second()
完成。阅读本手册,学习如何使用它

在阅读文档的同时,我建议您阅读,以进一步了解可用于处理多线程代码的功能


更新

为了更好地理解这个挑战,假设Leetcode使用这样的类来测试
Foo

公共类测试{
公共静态void main(字符串[]args)引发异常{
Foo-Foo=新的Foo();
线程t1=新线程(()->调用(foo::first,“first,”);
线程t2=新线程(()->调用(foo::second,“second”);
threadt3=新线程(()->调用(foo::third,“third.”);
//无序启动线程,线程之间有延迟,给每个线程
//如果没有充分编码以确保执行顺序,则有足够的时间完成。
t2.start();
睡眠(500);
t3.start();
睡眠(500);
t1.start();
//等待线程完成
t2.连接();
t3.join();
t1.join();
//此时,程序输出应为“第一、第二、第三”
}
接口方法{
公共void调用(Runnable printFirst)抛出InterruptedException;
}
私有静态void调用(FooMethod方法,字符串文本){
试一试{
方法调用(()->System.out.print(text));
}捕捉(中断异常e){
系统输出打印ln(e);
}
}
}
您无法修改此代码,因为它对您是隐藏的。您必须以某种方式将代码添加到
Foo
类中,以确保以正确的顺序调用3个
Runnable
对象

简单地向这3个方法添加
Thread.sleep()
调用并不是正确的解决方案,因为无论下面的测试在线程启动之间添加了多长时间的延迟,这都应该运行


您必须使用某种线程同步功能,例如,或。

Leetcode用于代码挑战,因此我们不应该给出完整的解决方案,因为这对您来说不会是一个挑战

所以这里有一个提示:使用两个对象,一个通知方法
second()
方法
first()
完成,另一个通知方法
third()
方法
second()
完成。阅读本手册,学习如何使用它

在阅读文档的同时,我建议您阅读,以进一步了解可用于处理多线程代码的功能


更新

为了更好地理解这个挑战,假设Leetcode使用这样的类来测试
Foo

公共类测试{
公共静态void main(字符串[]args)引发异常{
Foo-Foo=新的Foo();
线程t1=新线程(()->调用(foo::first,“first,”);
线程t2=新线程(()->调用(foo::second,“second”);
threadt3=新线程(()->调用(foo::third,“third.”);
//无序启动线程,线程之间有延迟,给每个线程
//如果没有充分编码以确保执行顺序,则有足够的时间完成。
t2.start();
睡眠(500);
t3.start();
睡眠(500);
t1.start();
//等待线程完成
t2.连接();
t3.join();
t1.join();
//此时,程序输出应为“第一、第二、第三”
}
接口方法{
公共void调用(Runnable printFirst)抛出InterruptedException;
}
私有静态void调用(FooMethod方法,字符串文本){
试一试{
方法调用(()->System.out.print(text));
}捕捉(中断异常e){
系统输出打印ln(e);
}
}
}
您无法修改此代码,因为它对您是隐藏的。您必须以某种方式将代码添加到
Foo
类中,以确保以正确的顺序调用3个
Runnable
对象

简单地向这3个方法添加
Thread.sleep()
调用并不是正确的解决方案,因为无论下面的测试在线程启动之间添加了多长时间的延迟,这都应该运行


您必须使用某种线程同步功能,例如,或。

一种简单得多的方法是将
信号灯
运行
获取
释放
方法一起使用:

class Foo {
    Semaphore runSecond;
    Semaphore runThird;

    public Foo() {
        runSecond = new Semaphore(0);
        runThird = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        runSecond.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        runSecond.acquire();
        printSecond.run();
        runThird.release();
    }

    public void third(Runnable printThird) throws InterruptedException {
        runThird.acquire();
        printThird.run();
    }
}

一个简单得多的方法是将
信号灯
run
A一起使用