【问题标题】:Implications of instantiating multiple Runnable with shared objects?使用共享对象实例化多个 Runnable 的含义?
【发布时间】:2019-03-23 04:50:29
【问题描述】:

我有一个打算多线程的程序。我有一个ProcessRunnable 类来处理需要大量 IO 的数据。 ProcessRunnable 类都在单独的线程中运行,但使用客户端/实用程序类的共享实例进行实例化。

例子:

Client client = new Client();
Util util = new Util();

List<Runnable> runnables = new ArrayList<>();

for (int i; i < THREAD_COUNT; i++) {
    runnables.add(ProcessRunnable
                       .builder()
                       .client(client)
                       .util(util)
                       .build());
}

runnables.forEach(runnable -> new Thread(runnable).start());

我很好奇在可运行文件中重用类的相同实例是否会阻塞行为并导致我的程序变成单线程?

【问题讨论】:

  • ^sweet^ 谢谢@AniketSahrawat
  • @GhostCat 很公平 - 获得积分!尽管有最佳实践,但感谢您参与讨论;)
  • 不用担心 - 再次感谢!
  • 不客气。请不要忘记删除不再需要的 cmets。

标签: java multithreading runnable


【解决方案1】:

这里:

runnable -> new Thread(runnable).start()

真正使您的代码成为多线程的关键点是您调用线程对象的 start() 方法。如果您只是调用线程类的 run 方法,那么您实际上最终会由“封闭”线程完成所有工作。

最后,请注意,直接使用“裸”线程并不理想。了解这一点是可以的,但 Java 提供了重要的抽象,例如 ExecutorService,出于各种原因应该使用它们。

避免使用原始线程的主要原因:您必须手动控制所有细微的细节。应该使用多少线程?池和共享线程怎么样(创建线程会带来很多开销,因此在现实世界中,您避免为单个任务创建线程然后将它们丢弃,就像您的代码一样)。除此之外:通常您想解决业务问题。您想使用多个线程来防止出现瓶颈情况。示例:您希望通过网络并行发出多个请求以获取和处理数据。那么你真的只关心最终结果,而不关心底层线程的细微之处!然后,您可以使用 Future 或 CompleteableFuture 对象。

只需使用搜索引擎并研究这些术语,您就会发现大量材料。

【讨论】:

  • 感谢您的评论!您是否介意详细说明使用 ExecutorService 提供的优势,或者推荐任何您认为特别有启发性的阅读材料?线程通过 BlockingQueues/BlockingDeques 共享状态 - 我发现根据 BlocksQueues 适当地管理/结束线程相对简单,但当然希望了解更好的做事方式!
  • 上面显示的代码被简化为原始问题的范围。使用的线程不会被丢弃,而是长时间运行,并且一次从 PriorityBlockingQueue 中提取一项来处理。我肯定看到如何使用 ExecutorService 来管理线程来改进这一点。目前,所有处理步骤都封装在 ProcessRunnable 中,包括多个 IO 调用 - 您认为拆分每个步骤并在所有 IO 上使用 CompletableFuture 与提交 Runnables 列表以供执行程序服务处理/执行会有性能差异吗?
  • 另外 - 我知道如何使用搜索引擎!不要轻率或懒惰,只是问问自己是否找到了任何您认为以特别有用的方式解释或展示事物的来源。你似乎有足够的信心去问这个问题!
猜你喜欢
  • 1970-01-01
  • 2016-03-07
  • 2010-12-29
  • 2020-11-18
  • 2018-01-27
  • 2014-12-29
  • 2018-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多