这应该是多线程上的一个简单问题:https://leetcode.com/problems/print-in-order/“同一个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();
}
**看来我可以用线程解决它。如下所示加入,但我不明白的是,为什么他们会将Runnable实例传递给每个方法,以及如何正确地执行,因为下面的代码将打印每条消息两次,一次是因为线程。start()将调用相应的run()方法,并且一次直接调用该方法。我知道这样做是错误的,但如果我们尝试使用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");
}
}```
一个更简单的方法是使用Semaphore
和run
、获取
、发布
方法:
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();
}
}
Leetcode是针对代码挑战的,所以我们不应该给出完整的解决方案,因为这对你来说不是挑战。
这里有一个提示:使用两个CountDownLatch
对象,一个通知方法第二()
方法first()
完成,另一个通知方法第三()
方法第二()
完成。阅读留档以了解如何使用它。
在阅读文档的同时,我建议您阅读软件包文档,以进一步了解可用于处理多线程代码的功能。
更新
为了更好地理解这个挑战,假设Leetcode使用这样的类来测试Foo类。
public class Test {
public static void main(String[] args) throws Exception {
Foo foo = new Foo();
Thread t1 = new Thread(() -> call(foo::first, "first,"));
Thread t2 = new Thread(() -> call(foo::second, "second,"));
Thread t3 = new Thread(() -> call(foo::third, "third."));
// Start threads out of order, with delay between them, giving each thread
// enough time to complete, if not adequately coded to ensure execution order.
t2.start();
Thread.sleep(500);
t3.start();
Thread.sleep(500);
t1.start();
// Wait for threads to complete
t2.join();
t3.join();
t1.join();
// At this point, the program output should be "first,second,third."
}
interface FooMethod {
public void call(Runnable printFirst) throws InterruptedException;
}
private static void call(FooMethod method, String text) {
try {
method.call(() -> System.out.print(text));
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
您无法修改此代码,因为它对您是隐藏的。您必须以某种方式向Foo类添加代码,以确保以正确的顺序调用3个可运行的对象。
只需添加线程。sleep()
调用这3个方法并不是正确的解决方案,因为无论下面的测试在线程启动之间添加多长时间的延迟,都应该运行该方法。
您必须使用某种线程同步功能,例如监视器、锁或同步器。
1) 当我将它输入到python解释器中时,我得到的输出是“this”,然后是零除法错误。但是,我引用的站点提到函数调用是第二高的优先级,所以不是应该先执行print的两个函数调用吗?我知道有短路评估,但这不是只有当你达到and、nots和OR的优先级时才会起作用吗? 2) 有人能解释一下我遗漏了什么,以及如何判断python将按照什么顺序执行一个逻辑表达式吗?
我正在尝试提出一种解决方案,它涉及在连接操作之后应用一些逻辑,从多个中的中选择一个事件。这类似于reduce函数,但它只返回1个元素,而不是递增地返回。因此最终结果将是单个(,对,而不是一个 每个键保证只到达一次。 假设像上面这样的连接操作,它用4个生成了1个,成功地连接并收集在。现在,我想做的是,立即访问这些值,并执行一些逻辑以将正确匹配到一个。例如,对于上面的数据集,我需要(,和)。 将为每个
所以我一直在读Kafka的语义学,我对它的工作原理有点困惑。 我理解生产者如何避免发送重复的消息(以防代理的ack失败),但我不明白的是,在消费者处理消息但在提交偏移量之前崩溃的情况下,一次是如何工作的。Kafka不会在这种情况下重试吗?
问题内容: 我可以理解以下定义: 每个对象都有一个标识,一个类型和一个值。一旦创建了对象,其身份就永远不会改变。您可能会认为它是对象在内存中的地址。所述操作者比较两个对象的身份; 该函数返回一个表示其身份的整数。 我认为上面的定义在创建“某物”时起作用,例如: 但是我不理解: 我还没有创建任何东西。那么整数“ 1”如何具有ID?这是否意味着只要我在Python Shell中“提及” 1,便立即将其
问题内容: 我已经在eclipse中创建了一个项目,并添加了Maven依赖项。在Eclipse中,它表示我正在使用JRE 1.5。一切在Eclipse中都可以正常运行,例如,我可以运行测试。 当我尝试从终端运行时,出现以下错误。 …在-source 1.3中不支持泛型(使用-source 5或更高版本来启用泛型)… 看来,Maven认为我正在使用JRE 1.3,并且无法识别泛型或for-each循
问题内容: 在碰到此链接http://www.javacodegeeks.com/2013/01/java-thread-pool-example-using- executors-and-threadpoolexecutor 之后,这是我第一次为新项目使用Java线程池。 .html ,我对此更加困惑,这是页面中的代码, 在代码中,创建了一个固定大小的池并创建了10个工作线程,对吗? 线程池应该