【问题标题】:Java - Thread using executor serviceJava - 使用执行器服务的线程
【发布时间】:2020-05-18 13:55:30
【问题描述】:

我正在学习 java 中的执行器服务。 要求是使用执行器服务创建 4 个线程 -

线程 1 - 获取两个数字作为输入。

线程 2 - 两个数字相加

线程 3 - 两个数字的乘法

线程 4 - 打印结果。

线程 1 应该先执行,线程 1 完成后线程 2、3 可以同时开始处理,最后线程 2、3 完成。线程 4 应该最终运行。

我们如何确定哪个线程首先启动以及接下来同时启动哪些线程。最后执行哪个线程。

注意:我们如何在不使用线程睡眠的情况下实现这一点。线程 1 完成后动态地立即启动其他两个线程。

【问题讨论】:

  • 线程 1 可以启动线程 2 和 3(也可能是线程 4)。线程 4 可以加入所有线程。
  • 您尝试了哪些方法,哪些方法无效?
  • 仅供参考,这个练习可能会教你一些关于如何使用线程的知识,但它绝对是为什么使用线程的最糟糕的例子。这就像,有人教你如何操作汽车,让你使用汽车的前保险杠将钉子钉在你正在建造的一件家具上。我是认真的。这个例子那个不好。如果一个程序需要以某种顺序执行某些事情,那么唯一正确的方法就是在一个线程中完成所有这些事情。线程的全部意义在于使您能够并发(这意味着,没有特定的顺序。)
  • 另请注意:不要将执行程序服务视为创建线程的一种方式。将其视为执行后台任务的一种方式。 执行器服务的全部意义在于尽可能地让您不必考虑它用来执行的“工作线程”你的任务。

标签: java multithreading java-8 executorservice scheduledexecutorservice


【解决方案1】:

首先,请阅读我对您最初问题的评论——关于使用汽车钉钉子的评论。

好的,现在,@dan1st 对如何构建解决方案有了一些想法。还有两个。

  1. 使用全局 int 变量、全局 lockwait()notifyAll():让每个线程进入一个 synchronized(lock) 块,其中包含它

    • 循环,调用 lock.wait() 直到全局 int 具有特定值,
    • 成功了,
    • 将全局 int 设置为将触发下一个线程的值,
    • 调用lock.notify(),最后
    • 退出
  2. 使用Semaphores:将两个Semaphore 实例传递给每个线程。称他们为inout 或类似的名称。有每个线程

    • 请致电in.acquire(),等待轮到,
    • 做它的伎俩,
    • 致电out.release()
    • 然后退出。

然后您的主例程负责创建信号量,并将它们传递给新线程,这样每个线程的out 与预期执行的线程的in 引用相同的信号量后续任务。


IMO,选项 2 更优雅,因为如果您的老师下周要求您通过在序列中间添加另一个步骤来修改您的程序,那么您编写的现有任务没有将不得不改变。您只需要编写新任务并在 main() 例程中更改两三行即可。

听起来并没有太大的改进,而且选项 2 显然比选项 1 需要更多的工作,但是如果您曾经受雇于具有数百万行代码的企业级软件系统代码,你会体会到选项 2 的美妙之处。

【讨论】:

  • PS,如果我曾经教过编程课,我的学生会学得很快,期待,“现在,改变你上周写的程序,这样......”在现实世界中,要求改变。经常。开发人员可以学习的最重要的技能之一是如何编写不必在每次需求发生变化时都从头开始的代码。
【解决方案2】:

您可以通过多种方式做到这一点。

例如,加入

一个线程可以加入另一个线程,这意味着它一直等到另一个线程完成。线程 2 和 3 可以加入线程 1,线程 4 可以加入线程 2 和 3。

另一种可能性是等待并发出信号,但我不确定它是否满足您的要求(它使用类似于Thread.sleep():

首先,您创建一个普通的java.util.concurrent.locks.Lock 并使用.newCondition() 创建此锁的条件您还使用newCondition() 创建第二个条件。

在调用awaitsignal/signalAll之前,必须锁定锁。

线程 2 和 3 在启动前的第一个条件下调用 .await(),线程 1 在完成时在第一个条件下调用 .signalAll

线程 4 在启动之前在第二个条件下调用 .await()

最后完成的线程(2或3)(线程首先完成的逻辑应该与锁同步)在第二个条件下调用.signal()

线程也可以互相启动

线程 1 在任务完成后启动线程 2 和 3,但我会向您推荐线程 4 的其他机制之一。

[免责声明]

如果您使用ExecutorService,您可能无法直接与线程交互。 This post 可能会帮助您加入,等待/信号应该不会更困难,如果需要,线程还可以将任务安排到线程池。

【讨论】:

  • 非常感谢。我在基本的 java 线程概念中理解了你的想法。这个概念在 java 8 中是否也一样..?
猜你喜欢
  • 1970-01-01
  • 2017-05-13
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
相关资源
最近更新 更多