面试姊妹篇4:常见的Java多线程面试题

主要内容

  • 本文主要记录多线程相关的操作问题,这些问题主要出现在一些面试中,当然学会了对本身的代码能力也有提升。

目录

本文源码

系列文章


1 、 交 替 多 线 程 \color{7f1A8A}1、交替多线程 1线

  • 题目描述:两个线程,一个存有数组1、2、3和另一个存有a、b、c,然后通过调度,最终结果输出1a2b3c
  • 设计思路:通过在while循环中加入判断,依次输出
  • 主要源码
public class demo01 {

    static volatile boolean flag = false;
    static String[] array_alpha = {"A", "B", "C"};
    static int[] array_num = {1, 2, 3};

    public static void main(String[] args) {

        Thread t_alpha = new Thread() {
            int count = 0;
            @Override
            public void run() {
                while (count < array_alpha.length) {
                    if (flag) {
                        System.out.print(array_alpha[count] + " ");
                        count++;
                        flag = !flag;
                    }
                }
            }
        };


        Thread t_num = new Thread() {
            int count = 0;
            @Override
            public void run() {
                while (count < array_num.length) {
                    if (!flag) {
                        System.out.print(array_num[count] + " ");
                        count++;
                        flag = !flag;
                    }
                }
            }
        };

        t_alpha.start();
        t_num.start();
    }
}

2 、 发 令 枪 问 题 \color{7f1A8A}2、发令枪问题 2

  • 题目描述:百米赛跑,4名运动员选手到达场地等待裁判口令,裁判一声口令,选手听到后同时起跑,当所有选手到达终点,裁判进行汇总排名
  • 设计思路:使用CountDownLatch来实现统一。
  • 主要源码
public class demo02 {
    
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final CountDownLatch cdOrder = new CountDownLatch(1);
        final CountDownLatch cdAnswer = new CountDownLatch(4);

        for (int i = 0; i < 4; i++) {
            Runnable runnable = new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    System.out.println("选手" + Thread.currentThread().getName() + "正在等待裁判发布口令");
                    cdOrder.await();
                    System.out.println("选手" + Thread.currentThread().getName() + "已接受裁判口令");
                    Thread.sleep((long) (Math.random() * 3_000));
                    System.out.println("选手" + Thread.currentThread().getName() + "到达终点");
                    cdAnswer.countDown();
                }
            };
            service.execute(runnable);
        }
        try {
            Thread.sleep((long) (Math.random() * 3_000));
            System.out.println("裁判" + Thread.currentThread().getName() + "即将发布口令");
            cdOrder.countDown();
            System.out.println("裁判" + Thread.currentThread().getName() + "已发送口令,正在等待所有选手到达终点");
            cdAnswer.await();
            System.out.println("所有选手都到达终点");
            System.out.println("裁判" + Thread.currentThread().getName() + "汇总成绩排名");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.shutdown();
    }
}

3 、 多 线 程 顺 序 执 行 \color{7f1A8A}3、多线程顺序执行 3线

  • 题目描述:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
  • 设计思路:使用Join实现线程顺序执行
  • 主要源码
public class demo03 extends Thread{
    public demo03(String name){
        setName(name);
    }

    @SneakyThrows
    @Override
    public void run() {
        Thread.sleep(1_000);
        System.out.println("i am "+ this.currentThread().getName());
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new demo03("t1");
        Thread t2 = new demo03("t2");
        Thread t3 = new demo03("t3");

        t1.start();
        t1.join();
        t2.start();
        t2.join();
        t3.start();
        t3.join();
    }
}

4 、 关 于 饥 饿 死 锁 \color{7f1A8A}4、关于饥饿死锁 4饿

  • 下面的运行结果应该输出什么?
public class ljtest{

    private static ExecutorService executorService = Executors.newSingleThreadExecutor();

    static class t1 implements Callable<String> {

        @Override
        public String call() throws Exception {
            System.out.println("i am t1");
            return "t1===";
        }
    }

    static class t2 implements Callable<String> {

        @Override
        public String call() throws Exception {
            System.out.println("i am t2");
            Future<String> submit = executorService.submit(new t1());
            return "t2===" + submit.get();
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        t2 t = new t2();
        Future<String> submit = executorService.submit(t);
        System.out.println(submit.get());
        System.out.println("la~la~la~");
        executorService.shutdown();
    }
}
  • 你期待的:
i am t2
i am t1
t2===t1===
la~la~la~
  • 实际上:只有这个
i am t2
  • 原因分析
    • 我们用到的线程池是Executors.newSingleThreadExecutor();他是只有一个线程的线程池。
    • 当我们把t2放进去执行的时候,t2又把t1放进去了,这个时候t1在等t2结束,t2在等t1的返回值,出现饥饿等待。

5 、 线 程 数 设 置 为 多 少 合 适 ? \color{7f1A8A}5、线程数设置为多少合适? 5线?

  • 题目:线程数设置为多少合适
  • 理论上,单核CPU一直工作的话,只能处理一个线程。如果该线程一半时间在处理数据,一半时间在等IO,那么这个单核CPU可以处理两个线程。
  • 因此类推出:
    • 确定机器是几核的:n核
    • 确定该线程的工作状态:有1/k的时间在处理计算,那么每核CPU可以处理k个线程。
    • 结论:该机器线程数设置的合适数量是:(n*k)个线程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值