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

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

目录

一、两个线程同时执行

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


编程达人
+关注
目录
打赏
0
0
0
0
83
分享
相关文章
|
9天前
|
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
47 0
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
149 83
Java 无锁方式实现高性能线程实战操作指南
本文深入探讨了现代高并发Java应用中单例模式的实现方式,分析了传统单例(如DCL)的局限性,并提出了多种无锁实现方案。包括基于ThreadLocal的延迟初始化、VarHandle原子操作、Record不可变对象、响应式编程(Reactor)以及CDI依赖注入等实现方式。每种方案均附有代码示例及适用场景,同时通过JMH性能测试对比各实现的优劣。最后,结合实际案例设计了一个高性能配置中心,展示了无锁单例在实际开发中的应用。总结中提出根据场景选择合适的实现方式,并遵循现代单例设计原则以优化性能和安全性。文中还提供了代码获取链接,便于读者实践与学习。
47 0
Java虚拟线程:轻量级并发的革命性突破
Java虚拟线程:轻量级并发的革命性突破
155 83
说一说 JAVA 内存模型与线程
我是小假 期待与你的下一次相遇 ~
说一说 Java 是如何实现线程间通信
我是小假 期待与你的下一次相遇 ~
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
98 5
Java 多线程最新实操技术与应用场景全解析:从基础到进阶
本文深入探讨了Java多线程的现代并发编程技术,涵盖Java 8+新特性,如CompletableFuture异步处理、Stream并行流操作,以及Reactive编程中的Reactor框架。通过具体代码示例,讲解了异步任务组合、并行流优化及响应式编程的核心概念(Flux与Mono)。同时对比了同步、CompletableFuture和Reactor三种实现方式的性能,并总结了最佳实践,帮助开发者构建高效、扩展性强的应用。资源地址:[点击下载](https://pan.quark.cn/s/14fcf913bae6)。
118 3
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问