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 是如何实现线程间通信的?


相关文章
|
9月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
9月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
11月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
500 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
11月前
|
缓存 Java 关系型数据库
Java 面试经验总结与最新 BAT 面试资料整理含核心考点的 Java 面试经验及最新 BAT 面试资料
本文汇总了Java面试经验与BAT等大厂常见面试考点,涵盖心态准备、简历优化、面试技巧及Java基础、多线程、JVM、数据库、框架等核心技术点,并附实际代码示例,助力高效备战Java面试。
494 0
|
11月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
1489 0
|
11月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
687 0
|
8月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
764 0
|
8月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
321 6
|
9月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
595 16