当前位置 : 主页 > 编程语言 > java >

Java面试题:实现线程间通信和线程等待

来源:互联网 收集:自由互联 发布时间:2023-02-04
(目录) 一、两个线程同时执行 需求:假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字 实现代码 package com.example;public class Demo { public static void prin

(目录)

一、两个线程同时执行

需求:假设有两个线程,一个是线程 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 是如何实现线程间通信的?

上一篇:kotlin的拓展函数和原理
下一篇:没有了
网友评论