1、主线程调用join
public class Main1 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程执行完成");
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
2、主线程、子线程调用join
public class Main2 {
public static void main(String[] args) {
final Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
});
thread1.start();
final Thread thread2 = new Thread(() -> {
try {
thread1.join();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
});
thread2.start();
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
3、wait
public class Main3 {
public static void main(String[] args) {
Object obj = new Object();
final Thread thread1 = new Thread(() -> {
synchronized (obj) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
obj.notify();
}
});
thread1.start();
synchronized (obj) { // current thread is not owner
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("主线程执行完成");
}
}
4、线程池
public class Main4 {
static ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
executor.submit(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
});
Future<?> future = executor.submit(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
});
while (!future.isDone()) {
}
System.out.println("主线执行完成");
executor.shutdown();
}
}
5、Condition
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main5 {
public static void main(String[] args) {
final List<Boolean> flagList = Arrays.asList(false, false);
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
final Thread thread1 = new Thread(() -> {
lock.lock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
condition1.signal();
flagList.set(0, true);
lock.unlock();
});
thread1.start();
final Thread thread2 = new Thread(() -> {
lock.lock();
if (!flagList.get(0)) {
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
flagList.set(1, true);
condition2.signal();
lock.unlock();
});
thread2.start();
try {
lock.lock();
if (!flagList.get(1)) {
condition2.await();
}
lock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
6、CountDownLatch
import java.util.concurrent.CountDownLatch;
public class Main6 {
public static void main(String[] args) {
// 计数器
CountDownLatch countDownLatch1 = new CountDownLatch(1);
CountDownLatch countDownLatch2 = new CountDownLatch(1);
final Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
countDownLatch1.countDown();
});
thread1.start();
final Thread thread2 = new Thread(() -> {
try {
countDownLatch1.await();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
countDownLatch2.countDown();
});
thread2.start();
try {
countDownLatch2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
7、CyclicBarrier
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Main7 {
public static void main(String[] args) {
// 回环栅栏
CyclicBarrier cyclicBarrier1 = new CyclicBarrier(2);
CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2);
final Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
try {
cyclicBarrier1.await(); // 放开栅栏
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
thread1.start();
final Thread thread2 = new Thread(() -> {
try {
cyclicBarrier1.await();// 放开栅栏
Thread.sleep(1000);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
try {
cyclicBarrier2.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
thread2.start();
try {
cyclicBarrier2.await();
} catch (InterruptedException |
BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
8、Semaphore
import java.util.concurrent.Semaphore;
public class Main8 {
public static void main(String[] args) {
// 信号量
Semaphore semaphore1 = new Semaphore(0);
Semaphore semaphore2 = new Semaphore(0);
final Thread thread1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程1执行完成");
semaphore1.release(); // 释放许可
});
thread1.start();
final Thread thread2 = new Thread(() -> {
try {
semaphore1.acquire();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程2执行完成");
semaphore2.release(); // 释放许可
});
thread2.start();
try {
semaphore2.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完成");
}
}
说明:一般测试的时候,还可以让线程休眠等待,但是这种方式控制不是特别好,建议使用上面这些方法。