栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java面试题】有三个线程 t1,t2,t3,怎么确保它们按顺序执行?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java面试题】有三个线程 t1,t2,t3,怎么确保它们按顺序执行?

方案有三:
  1. 【线程 t1】代码执行完,调用【线程t2】的start()方法,【t2】执行完调用【线程t3】的start()方法;
  2. 使用线程间通信,3个线程使用同一把锁,【线程t1】执行完后,使用 JUC 中 signal()/signalAll() 方法唤醒【线程t2】,以此类推;
  3. 【推荐使用】 使用线程为我们提供的 join() 方法。

备注:
  代码中使用 sleep() 也是为了更方便复现问题

方案一

  方案一是最 low 的一种方式,不做介绍,不建议使用

public class SortThread1 {

    public static void main(String[] args) throws InterruptedException {
        
        Thread t3 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t3");


        Thread t2 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
                // 执行线程3
                t3.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t2");

        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
                // 执行线程2
                t2.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1");

        // 执行线程1
        t1.start();
    }
}
方案二

  采用线程间通信。三个线程同时启动,使用一把锁。三个线程 t1,t2,t3,按顺序执行,线程 t1 执行完成后,通知线程 t2 ,t2 获取锁后,继续执行,以此类推

public class SortThread2 {

    public static void main(String[] args) {
        // 创建Lock
        Lock lock = new ReentrantLock();

        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();

        Thread t1 = new Thread(() -> {
            // 加锁
            lock.lock();
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
                // 唤醒t2线程
                condition2.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放锁
                lock.unlock();
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            // 加锁
            lock.lock();
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
                // 唤醒t3线程
                condition3.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放锁
                lock.unlock();
            }
        }, "t2");

        Thread t3 = new Thread(() -> {
            // 加锁
            lock.lock();
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放锁
                lock.unlock();
            }
        }, "t3");

        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}
方案三

  【推荐使用】使用线程为我们提供的 join() 方法。join() 方法会等待当前线程,join(0)则会一直等待线程死亡。join() 和 join(long millis) 方法源码,如下图所示:


public class SortThread3 {

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1");

        Thread t2 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t2");

        Thread t3 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + "线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t3");

        t1.start();
        t1.join();   // 一直等待t1执行,线程死亡后,执行线程t2
        t2.start();
        t2.join();   // 一直等待t2执行,线程死亡后,执行线程t3
        t3.start();
        t3.join();   // 一直等待t3执行,线程死亡后,执行主线程

 		//  使用带参数join()方法
        // t1.start();
        // t1.join(10);  // 等待t1线程10ms,t1线程代码内sleep 2s,则不再继续等待t1,执行t2线程
		// t2.start();
		// t2.join(10);  // 等待t2线程10ms,t2线程代码内sleep 3s,则不再继续等待t2,执行t2线程
		// t3.start();
		// t3.join(10);  // 等待t3线程10ms,t3线程代码内sleep 1s.因为 sleep 等待时间原因,最终输出结果是:【t3执行 > t1执行 > t2执行 > main主线程】
    }
}

博主写作不易,加个关注呗

求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙

我不能保证所写的内容都正确,但是可以保证不复制、不粘贴。保证每一句话、每一行代码都是亲手敲过的,错误也请指出,望轻喷 Thanks♪(・ω・)ノ

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/355777.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号