问题如下:
三个线程同时启动如下:
t1.start();
t2.start();
t3.start();
第一个线程(t1)的输出应该是第二个线程(t2)的输入,第二个线程(t2)的输出应该是第三个线程(t3)的输入。
你能告诉我其中的逻辑吗?
我知道我们可以使用对象的等待和通知方法。但是我可以得到实现这个输出的算法或逻辑吗?
问题如下:
三个线程同时启动如下:
t1.start();
t2.start();
t3.start();
第一个线程(t1)的输出应该是第二个线程(t2)的输入,第二个线程(t2)的输出应该是第三个线程(t3)的输入。
你能告诉我其中的逻辑吗?
我知道我们可以使用对象的等待和通知方法。但是我可以得到实现这个输出的算法或逻辑吗?
There are several ways to doing this. As point out by Jon, there's not point in running threads this way as you are causing them to me blocked on the output of other threads, effectively not achieving parallelization.
My "preferred" solution would be use ExecutorService
, as mentioned by Peter, albeit a bit differently. Here's one naive approach.
ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<String> output1 = executor.submit(new Callable<String>() {
@Override public String call() {
// do Something
return "a String from Task #1";
}
});
final Future<String> output2 = executor.submit(new Callable<String>() {
@Override public String call() throws Exception{
// do Something
// Wait for the output of the above task using `Future.get()`.
return output1.get() + ", a String from Task #2";
}
});
Future<String> output3 = executor.submit(new Callable<String>() {
@Override public String call() throws Exception{
// do Something
return output2.get() + ", a String from Task #3";
}
});
System.err.print("Output from 3rd task: " + output3.get());
Other ways to do this using threads: Shared Blocking Data Structure (e.g. BlockingQueue
between Threads to safely publish results. If no results are passed and just require a signal of termination to the other threads, you case use CountDownLatch
es.
这是为您准备的助手类。它在一个单例助手类中实现了两个资源锁。
让每个线程使用ResourceLock.getInstance()
. 让线程 2 调用getResource1()
并等待线程 1 完成并将其输出放入setResource1()
. 这释放了锁和线程二对getResource1()
返回的调用。
重复线程 2 和 3
在没有超时的情况下调用挂起函数并不是一个好主意。因此有 10 秒的超时,根据您的需要进行编辑。
package com.madinsweden.test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class ResourceLock {
protected static final int TIMEOUT = 10000; //ms
private CountDownLatch mLock1;
private CountDownLatch mLock2;
private Object mObject1;
private Object mObject2;
private static ResourceLock mInstance;
private ResourceLock() {
mLock1 = new CountDownLatch(1);
mLock2 = new CountDownLatch(1);
}
public static ResourceLock getInstance() {
if (null == mInstance) {
mInstance = new ResourceLock();
}
return mInstance;
}
public void setObject1(Object o) {
mObject1 = o;
mLock1.countDown();
}
public Object getResource1() {
try {
mLock1.await(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new RuntimeException("Timeout of resource lock 1");
}
return mObject1;
}
public void setObject2(Object o) {
mObject2 = o;
mLock2.countDown();
}
public Object getResource2() {
try {
mLock2.await(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new RuntimeException("Timeout of resource lock 2");
}
return mObject2;
}
}
我建议你使用 ExecutorServices。这意味着更容易在线程之间传递工作。
// fields
ExecutorServices service1 = ...
ExecutorServices service2 = ...
ExecutorServices service3 = ...
// Task1 submits to service2
service1.submit(new Task1());
// service2 submits to service3