我想同时执行两个方法,名为 A 和 B。
我也希望 B 等待 A 完成。
如何通过在 Java 中实现线程来实现这样的结果?
使用Thread#join()。在要等待死亡的线程对象上调用它。
join 方法允许一个线程等待另一个线程完成。
来自官方教程的示例:
public class SimpleThreads {
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName =
Thread.currentThread().getName();
System.out.format("%s: %s%n",
threadName,
message);
}
private static class MessageLoop
implements Runnable {
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
Thread.sleep(4000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
}
public static void main(String args[])
throws InterruptedException {
// Delay, in milliseconds before
// we interrupt MessageLoop
// thread (default one hour).
long patience = 1000 * 60 * 60;
// If command line argument
// present, gives patience
// in seconds.
if (args.length > 0) {
try {
patience = Long.parseLong(args[0]) * 1000;
} catch (NumberFormatException e) {
System.err.println("Argument must be an integer.");
System.exit(1);
}
}
threadMessage("Starting MessageLoop thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for MessageLoop thread to finish");
// loop until MessageLoop
// thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second
// for MessageLoop thread
// to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting!");
t.interrupt();
// Shouldn't be long now
// -- wait indefinitely
t.join();
}
}
threadMessage("Finally!");
}
}
这是您应该能够开始使用的示例双线程代码片段:
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if (i != null) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue queue = new LinkedBlockingQueue();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
你需要的是Future
Java类。访问异步调用的方法的结果非常简单。
检查 Javadocs http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html以获得更好的解释。
干杯
我不确定您所说的“我希望 B 等待 A 完成”是什么意思,我认为它的意思是 B 需要在 A 之后运行。
您可以使用 轻松完成此操作ExecutorService
,在此示例中它是 a singleThreadExecutorService
,因此可以保证在 A 之后运行 B。
唯一的问题是,如果 A 出现问题退出,它将不会被拾取,因此您可能希望分配一个看门狗线程来使用该Future.get
方法获取 A 的状态,然后在 A 成功时调度 B。
public static Object a() {
return new Object();
}
public static Object b() {
return new Object();
}
public static class CallA implements Callable<Object> {
public Object call() throws Exception {
return a();
}
}
public static class CallB implements Callable<Object> {
public Object call() throws Exception {
return b();
}
}
public static void main(String[] args) {
final ExecutorService executorService = Executors.newSingleThreadExecutor();
final Future<Object> aFuture = executorService.submit(new CallA());
final Future<Object> bFuture = executorService.submit(new CallB());
try {
aFuture.get();
bFuture.get();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
我建议你不要弄乱Thread
s 除非你知道你在做什么 - 它可能会导致危险的道路。使用Executor
提供的 s,您遇到并发问题的可能性要小得多。
在公共对象上使用等待和通知方法
Class ClassA implements runnable{
Message messageA;
public ClassA(Message messageA){
this.messageA = messageA;
}
public void run(){
//code here
messageA.notify();
}
}
Class ClassB implements runnable{
Message messageA;
public ClassB(Message messageA){
this.messageA = messageA;
}
public void run(){
messageA.wait();
//code here
}
}
public static void main(){
Message message = new Message();// a simplest object here can be String
//ctreate thread of ClassA(message);
//create thread of classB(message);
}
线程 B 将等待,直到线程 A 发送消息对象的通知。
在此处使用 oracle javadocs 中的 Thread#join()