目录
- 一、两个线程同时执行
- 二、一个线程去等待另一个线程
- 三、两个线程交叉运行
- 四、一个线程去等待多个线程
- 五、多个线程之间互相等待
- 六、主线程获取子线程执行结果
一、两个线程同时执行
需求:假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字
实现代码
package com.example;
public class Demo {
public static void printNumbers(String threadName){
for (int i = 1; i <= 3; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
public static void main(String[] args) {
// 线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
printNumbers("Thread A");
}
});
// 线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
printNumbers("Thread B");
}
});
// 启动线程
threadA.start();
threadB.start();
}
}
输出结果
Thread B: 1
Thread A: 1
Thread B: 2
Thread A: 2
Thread B: 3
Thread A: 3
二、一个线程去等待另一个线程
需求: B 在 A 全部打印完后再开始打印
实现方法:使用thread.join()
实现代码
package com.example;
public class Demo {
public static void printNumbers(String threadName){
for (int i = 1; i < 4; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + ": " + i);
}
}
public static void main(String[] args) {
// 线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
printNumbers("Thread A");
}
});
// 线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("B 开始等待 A");
try {
threadA.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
printNumbers("Thread B");
}
});
// 启动线程
threadB.start();
threadA.start();
}
}
执行结果
B 开始等待 A
Thread A: 1
Thread A: 2
Thread A: 3
Thread B: 1
Thread B: 2
Thread B: 3
三、两个线程交叉运行
需求:A 在打印完 1 后,再让 B 打印 1, 2, 3,最后再回到 A 继续打印 2, 3。
实现方法:object.wait()
和 object.notify()
实现代码
package com.example;
public class Demo {
public static void main(String[] args) {
// 共享的对象锁
Object lock = new Object();
// 线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread A 等待锁");
synchronized (lock) {
System.out.println("Thread A 得到了锁 lock");
System.out.println("Thread A 1");
try {
// 交出锁的控制权
System.out.println("Thread A 准备进入等待状态,放弃锁 lock 的控制权 ");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 有人唤醒了 A, A 重新获得锁 lock");
System.out.println("Thread A 2");
System.out.println("Thread A 3");
}
}
});
// 线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread B 等待锁 ");
synchronized (lock) {
System.out.println("Thread B 得到了锁 lock");
System.out.println("Thread B 1");
System.out.println("Thread B 2");
System.out.println("Thread B 3");
System.out.println("Thread B 打印完毕,调用 notify 方法 ");
// 释放控制权
lock.notify();
}
}
});
// 启动线程
threadA.start();
threadB.start();
}
}
执行结果
Thread A 等待锁
Thread A 得到了锁 lock
Thread A 1
Thread A 准备进入等待状态,放弃锁 lock 的控制权
Thread B 等待锁
Thread B 得到了锁 lock
Thread B 1
Thread B 2
Thread B 3
Thread B 打印完毕,调用 notify 方法
Thread 有人唤醒了 A, A 重新获得锁 lock
Thread A 2
Thread A 3
四、一个线程去等待多个线程
需求:四个线程 A B C D,其中 D 要等到 A B C 全执行完毕后才执行,而且 A B C 是同步运行的
实现方式: CountdownLatch
实现代码
package com.example;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Demo {
public static void main(String[] args) {
// 创建一个计数器
int worker = 3;
CountDownLatch countDownLatch = new CountDownLatch(worker);
// 线程
new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread D");
}
}).start();
List<String> threadNames = Arrays.asList("Thread A", "Thread B", "Thread C");
for (String threadName : threadNames) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(threadName);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}).start();
}
}
}
执行结果
Thread A
Thread C
Thread B
Thread D
五、多个线程之间互相等待
需求:线程 A B C 各自开始准备,直到三者都准备完毕,然后再同时运行
实现方式: CyclicBarrier
实现代码
package com.example;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Demo {
public static void main(String[] args) {
// 创建一个计数器
int worker = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(worker);
final Random random = new Random();
List<String> threadNames = Arrays.asList("Thread A", "Thread B", "Thread C");
for (String threadName : threadNames) {
new Thread(new Runnable() {
@Override
public void run() {
int sleep = random.nextInt(1000) + 100;
System.out.println(threadName + " sleep: " + sleep);
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 等待
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
// 所有线程都准备好了,一起执行
System.out.println(threadName);
}
}).start();
}
}
}
执行结果
Thread A sleep: 989
Thread C sleep: 522
Thread B sleep: 1056
Thread B
Thread C
Thread A
六、主线程获取子线程执行结果
需求:子线程完成某件任务后,把得到的结果回传给主线程
实现方式: Callable + FutureTask
实现代码
package com.example;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class Demo {
public static void main(String[] args) {
// 计算0-100之和
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
int result = 0;
for (int i = 0; i <= 100; i++) {
result += i;
}
return result;
}
};
// 启动子线程计算
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
// 等待子线程结束,并获取计算结果
try {
Integer result = futureTask.get();
System.out.println("result: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
执行结果
result: 5050
参考
面试官:Java 是如何实现线程间通信的?