文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

农行一面:如何保证线程T1,T2,T3 顺序执行?

2024-11-29 17:44

关注

考察意图

在面试中出现这道问题,通常是为了考察候选人的以下几个知识点:

保证线程顺序执行的方法

在分析完面试题的考察意图之后,我们再分析如何保证线程顺序执行,这里列举了几种常见的方式。

1.join()

join()方法是Thread类的一部分,可以让一个线程等待另一个线程完成执行。当你在一个线程T上调用T.join()时,调用线程将进入等待状态,直到线程T完成(即终止)。因此,可以通过在每个线程启动后调用join()来实现顺序执行。

如下示例代码,展示了join()如何保证线程顺序执行:

Thread t1 = new Thread(() -> {
   // 线程T1的任务
});

Thread t2 = new Thread(() -> {
   // 线程T2的任务
});

Thread t3 = new Thread(() -> {
   // 线程T3的任务
});

t1.start();
t1.join(); // 等待t1完成

t2.start();
t2.join(); // 等待t2完成

t3.start();
t3.join(); // 等待t3完成

2.CountDownLatch

CountDownLatch通过一个计数器来实现,初始时,计数器的值由构造函数设置,每次调用countDown()方法,计数器的值减1。当计数器的值变为零时,所有等待在await()方法上的线程都将被唤醒,继续执行。

CountDownLatch是Java并发包(java.util.concurrent)中的一个同步辅助类,用于协调多个线程之间的执行顺序。它允许一个或多个线程等待另外一组线程完成操作。

如下示例代码,展示了CountDownLatch如何保证线程顺序执行:

CountDownLatch latch1 = new CountDownLatch(1);
CountDownLatch latch2 = new CountDownLatch(1);

Thread t1 = new Thread(() -> {
   // 线程T1的任务
   latch1.countDown(); // 完成后递减latch1
});

Thread t2 = new Thread(() -> {
   try {
       latch1.await(); // 等待T1完成
       // 线程T2的任务
       latch2.countDown(); // 完成后递减latch2
   } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
   }
});

Thread t3 = new Thread(() -> {
   try {
       latch2.await(); // 等待T2完成
       // 线程T3的任务
   } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
   }
});

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

CountDownLatch关键方法解析:

3.Semaphore

Semaphore通过一个计数器来管理许可,计数器的初始值由构造函数指定,表示可用许可的数量。线程可以通过调用acquire()方法请求许可,如果许可可用则授予访问权限,否则线程将阻塞。使用完资源后,线程调用release()方法释放许可,从而允许其他阻塞的线程获取许可。

如下示例代码,展示了Semaphore如何保证线程顺序执行:

Semaphore semaphore1 = new Semaphore(0);
Semaphore semaphore2 = new Semaphore(0);

Thread t1 = new Thread(() -> {
   // 线程T1的任务
   semaphore1.release(); // 释放一个许可
});

Thread t2 = new Thread(() -> {
   try {
       semaphore1.acquire(); // 获取许可,等待T1完成
       // 线程T2的任务
       semaphore2.release(); // 释放一个许可
   } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
   }
});

Thread t3 = new Thread(() -> {
   try {
       semaphore2.acquire(); // 获取许可,等待T2完成
       // 线程T3的任务
   } catch (InterruptedException e) {
       Thread.currentThread().interrupt();
   }
});

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

Semaphore关键方法分析:

4.单线程池

单线程池(Executors.newSingleThreadExecutor())可以确保任务按提交顺序依次执行。所有任务都会在同一个线程中运行,保证了顺序性。

如下示例代码展示了单线程池如何保证线程顺序执行:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new T1());
executor.submit(new T2());
executor.submit(new T3());
executor.shutdown();

单线程这种方法简单易用,适合需要顺序执行的场景。

5.synchronized

synchronized 是Java中的一个关键字,用于实现线程同步,确保多个线程对共享资源的访问是互斥的。它通过锁机制来保证同一时刻只有一个线程可以执行被Synchronized保护的代码块,从而避免数据不一致和线程安全问题。

如下示例代码,展示了synchronized如何保证线程顺序执行:

class Task {
    synchronized void executeTask(String taskName) {
        System.out.println(taskName + " 执行");
    }
}

public class Main {
    public static void main(String[] args) {
        Task task = new Task();
        new Thread(() -> task.executeTask("T1")).start();
        new Thread(() -> task.executeTask("T2")).start();
        new Thread(() -> task.executeTask("T3")).start();
    }
}

总结

在这篇文章中,我们分析了 5种保证线程顺序执行的方法,依次如下:

在实际开发中,需要在业务代码中去保证线程执行顺序的情况几乎不会出现,因此,这个面试题其实缺乏实际的应用场景,纯粹是为了面试存在。尽管是面试题,还是可以帮助我们更好地去了解和掌握线程。

来源:猿java内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯