【问题标题】:Java thread wait and notifyJava线程等待和通知
【发布时间】:2009-05-05 18:02:51
【问题描述】:

我有两个线程。线程 A 正在从队列中提取一些元素,线程 B 正在向队列中添加一些元素。

我希望线程 A 在队列为空时进入睡眠状态。

当线程 B 向队列中添加一些元素时,它应该确保线程 A 正在工作。如何在 Java 中做到这一点?

【问题讨论】:

    标签: java multithreading queue producer-consumer


    【解决方案1】:

    使用BlockingQueue,即:

    Queue 还支持在检索元素时等待队列变为非空的操作,以及在存储元素时等待队列中可用空间的操作。

    说真的,不要试图在这里重新发明轮子。




    (如果您必须使用等待/通知,请阅读this tutorial。但请不要让自己痛苦!)

    【讨论】:

      【解决方案2】:

      这里有一些细节:

      import java.concurrent.Executors;
      import java.concurrent.ExecutorService;
      ...
      ExecutorService executor = Executors.newFixedThreadPool(someNumberOfThreads);
      ...
      executor.execute(someObjectThatImplementsRunnable);
      ...
      executor.shutdownNow();
      

      这就是 Java 的新线程功能的全部内容。 Executor 是一个线程池,其中包含 someNumberOfThreads。它由阻塞队列提供。除非有工作要做,否则所有线程都会休眠。当您使用 execute() 方法将 Runnable 对象推送到队列中时,Runnable 对象将位于队列中,直到有可用的线程来处理它。然后,它的 run() 方法被调用。最后,shutdownNow() 方法向池中的所有线程发出信号以关闭。

      现在比以前简单多了。

      (对此有很多变体,例如具有最小和最大线程数的池,或者在调用 execute() 的线程将阻塞之前具有最大大小的队列。)

      【讨论】:

      • 请注意,这并不是您真正想要用于长寿命线程的内容。当你有一些你想要处理的短任务时,它更适合。例如,如果您有一个线程从队列中提取事件,然后对这些事件执行某些操作,那么从队列中提取事件的线程可能不应该被池化,但它可能会使用线程池来做任何事情同时处理每个事件。您永远不会希望池中的线程等待某些东西,尤其是在固定大小的池中。
      • 有趣。我很好奇这是什么原因。我们正在执行您在应用程序的几个地方所警告的事情,我很好奇这可能会给我们带来什么麻烦。
      • 线程池有两个主要目的:首先,您可以通过重用线程来减少线程创建开销,其次,您可以控制一次为多少个 Runnables 分配 CPU。这两个目的都非常适合 CPU 密集型任务,例如数字运算,以及您希望同时运行的其他短期任务。像消费者线程这样的东西会坐在那里等到有东西要消费,然后它会做它的事情,然后回到等待状态。它的大部分时间都花在等待上,这意味着池中的可用线程较少。
      • 现在,如果您使用的是非固定池,这不是问题,但是您会失去线程池的第二个目的:控制 CPU 绑定的并发级别任务。您可以创建两个线程池;一个为您的长期、非 CPU 绑定的东西提供无限大小,大部分时间都在等待系统的其他部分,为您的短期任务提供一个固定大小的池,但前一种类型的线程在线程池中并没有真正受益,并且可以说“提交任务”的范式不适合与应用程序本身具有相似生命周期的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-31
      • 2013-02-20
      • 1970-01-01
      • 2011-10-30
      • 1970-01-01
      相关资源
      最近更新 更多