在Java中,Thread.join()
方法用于等待一个线程执行完毕后再继续执行当前线程。以下是一些常见的线程协作技巧,这些技巧可以帮助你更好地控制线程的执行顺序和共享资源:
join()
方法来确保线程按照特定的顺序执行。例如,如果你有一个主线程和一个子线程,你可能希望主线程在子线程之前执行完毕。你可以通过在主线程中调用子线程的join()
方法来实现这一点。Thread t1 = new Thread(new Runnable() {
public void run() {
// 子线程的任务
}
});
t1.start();
t1.join(); // 主线程会等待t1执行完毕后再继续执行
// 接下来主线程的任务
wait()
方法用于使当前线程等待,直到另一个线程调用同一对象的notify()
或notifyAll()
方法。这可以用于线程间的协作,例如生产者-消费者问题。class Buffer {
private boolean empty = true;
public synchronized void put(Object item) throws InterruptedException {
while (!empty) {
wait(); // 如果缓冲区已满,则等待
}
empty = false;
notify(); // 通知等待的线程缓冲区非空
}
public synchronized Object take() throws InterruptedException {
while (empty) {
wait(); // 如果缓冲区为空,则等待
}
empty = true;
notify(); // 通知等待的线程缓冲区非满
return item;
}
}
CountDownLatch
是一个同步辅助类,它允许一个或多个线程等待直到一组操作完成。这在需要等待多个线程完成后再执行下一步操作的场景中非常有用。CountDownLatch latch = new CountDownLatch(3); // 等待3个线程完成
Thread t1 = new Thread(new Runnable() {
public void run() {
// 任务1
latch.countDown(); // 完成任务1
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
// 任务2
latch.countDown(); // 完成任务2
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
// 任务3
latch.countDown(); // 完成任务3
}
});
t1.start();
t2.start();
t3.start();
try {
latch.await(); // 主线程会等待所有任务完成后再继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
CyclicBarrier
是一个可重复使用的同步辅助类,它允许一组线程互相等待,直到所有线程都到达某个屏障(barrier)点。这在需要多个线程协同完成任务(如数据分片处理)的场景中非常有用。CyclicBarrier barrier = new CyclicBarrier(3); // 3个线程需要协同完成任务
Thread t1 = new Thread(new Runnable() {
public void run() {
// 任务1
try {
barrier.await(); // 等待其他线程完成任务
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
// 任务2(依赖于任务1和其他线程的结果)
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
// 任务2
try {
barrier.await(); // 等待其他线程完成任务
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
// 任务3(依赖于任务1和其他线程的结果)
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
// 任务3
try {
barrier.await(); // 等待其他线程完成任务
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
// 任务4(依赖于任务1、2和其他线程的结果)
}
});
t1.start();
t2.start();
t3.start();
这些技巧可以帮助你更好地控制线程的执行顺序和共享资源,从而实现更高效的并发编程。