多线程之间的协调(一):线程等待其它线程
2019-02-14 本文已影响0人
b91cbec6a902
如何让线程A等待线程B执行完以后再往下执行?
1、使用Object类的wait()和notifyAll()方法。
示意代码:
public class MyRunner implements Runnable {
private Object lock;
public MyRunner(Object lock) {
this.lock = lock;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread线程执行完了~");
synchronized (lock) {
lock.notifyAll();
}
}
}
@Test
public void test_0() throws InterruptedException {
Object lock = new Object();
Thread thread = new Thread(new MyRunner2(lock));
thread.start();
synchronized (lock) {
lock.wait();
}
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
主线程执行完了~
注意:wait()方法一定要在notifyAll()之前执行,否则线程会错失此次被唤醒的机会,然后一直等待下去。
示意代码:
@Test
public void test_0() throws InterruptedException {
Object lock = new Object();
Thread thread = new Thread(new MyRunner(lock));
thread.start();
Thread.sleep(2000);
synchronized (lock) {
lock.wait();
}
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
// 主线程一直处于等待中
2、使用Thread类的wait()方法。
线程结束时会自动唤醒等待在当前Thread对象上的所有线程。
示意代码:
@Test
public void test_1() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread线程执行完了~");
});
thread.start();
synchronized (thread) {
thread.wait();
}
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
主线程执行完了~
注意:wait()方法一定要在thread线程运行结束之前执行,否则主线程会错失此次被唤醒的机会,然后一直等待下去。
示意代码:
@Test
public void test_1() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread线程执行完了~");
});
thread.start();
Thread.sleep(2000)
synchronized (thread) {
thread.wait();
}
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
// 主线程一直处于等待中
3、使用Thread类的join()方法。
示意代码:
@Test
public void test_2() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread线程执行完了~");
});
thread.start();
thread.join();
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
主线程执行完了~
注意:使用join()方法不会出现前两种方法中主线程一直等待的情况。
示意代码:
@Test
public void test_2() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread线程执行完了~");
});
thread.start();
Thread.sleep(2000);
thread.join();
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
主线程执行完了~
join()方法解析:
public final void join() throws InterruptedException {
join(0);
}
// 先获取Thread对象的锁
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
// 判断该Thread对象是否运行结束,如果运行结束,则不等待。
// 从这里可以看出,当Thread对象运行结束后再调用Thread对象的join()方法,不会产生任何影响。
while (isAlive()) {
// 调用该Thread对象的wait方法
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从源码可以看出,Thread的join()方法是对Thread的wait()方法的包装,多了一步校验线程是否运行结束的操作。
4、使用CountDownLatch类。
实例代码:
public class MyRunner implements Runnable {
private CountDownLatch latch;
public MyRunner(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread执行完了~");
latch.countDown();
}
}
@Test
public void test_3() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
Thread thread = new Thread(new MyRunner(latch));
thread.start();
latch.await();
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
主线程执行完了~
如何让线程A等待多个线程执行完以后再往下执行?
使用CountDownLatch类。
示意代码:
@Test
public void test_4() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
Thread thread_1 = new Thread(new MyRunner(latch));
thread_1.start();
Thread thread_2 = new Thread(new MyRunner(latch));
thread_2.start();
latch.await();
System.out.println("主线程执行完了~");
}
运行结果:
thread线程执行完了~
thread线程执行完了~
主线程执行完了~