【问题标题】:ScheduledExecutorService and Threads in JavaJava 中的 ScheduledExecutorService 和线程
【发布时间】:2014-09-24 08:39:54
【问题描述】:

调度程序在这里是如何工作的?它是否在后台创建一个新线程并像回调一样在主线程中执行 Run 方法。 ? .当run方法被执行时,它是否属于主线程?

 classA implements Runnable
 {
     
    public void Run()
    {
       System.out.println(Thread.currentTread().getName());
    }
    
    public static void main(String args[])
    {
      Thread.currentThread().setName("Main");
    
      ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
      scheduler.scheduleAtFixedRate(this, 250, 250, TimeUnit.MILLISECONDS);
    
    } 
}

谢谢。

【问题讨论】:

  • “是否在后台创建新线程” 是和否。当您构造执行器时,它会创建并汇集一个线程。 “当run方法被执行时,它是否属于主线程?” - 不,它在执行器创建时创建的池Thread中运行......
  • 感谢您的帮助。我不知道 run() 在新创建的后台线程中执行。有没有办法可以在主线程中使用计时器或 ScheduledExecutorService 执行方法?
  • 很多使用定时器的方法。如果你想使用 ScheduledExecutorService,你应该提供它 ThreadFactory,它返回当前线程。即 Executors.newSingleThreadScheduledExecutor((r) -> Thread.currentThread());
  • 我需要做的是在定时器关闭时在主线程中执行一个方法(可能的 run() 方法)。

标签: java multithreading scheduledexecutorservice


【解决方案1】:

SingleThreadScheduledExecutor 是如何工作的?

它创建一个最多包含一个线程的线程池。这样可以确保一次只有一个任务(在此执行程序上安排)运行。
任务在执行者的单线程中运行,而不是在提交它们的线程上。

你能让方法在“主线程”上运行吗?*

你可以“制造”任何东西,对吧?但不是与 ExecutorService 一起使用,它旨在与自己的线程一起工作。

那怎么办?

基本上,要么您处于一个为您提供一切的环境(例如 Swing 中的 UI 应用程序),所以请检查您的情况(Swing 具有事件调度线程)。要么你需要一些工作。因此,我首先建议您确保在继续执行此工作之前确实需要在主线程中工作。

这项工作涉及什么?

无需任何特殊工作,您的主线程就会执行不可中断的语句流代码。它们只写一次,没有人可以将代码“注入”到你的主线程中(好吧,除非你的记忆真的很乱,你可以这样做,但这不是人们通常会做的事情)。

所以你的主线程正忙于执行任务 A,然后是 B,然后是 C,然后是 D,​​以尽可能快的速度(或允许的速度)。您不能在此流程中间注入“任务 E”。

打个比方,这相当于在代码中随机选择一行,并在此处添加另一个方法的语句:保证崩溃(上下文是什么,堆栈是什么,此特定行存在什么变量,以及哪个值:不可预测)。这不可能发生。

因此,即使任务 A 是“创建一个要在 4 秒内执行的任务”,将会发生的情况是:在另一个线程中,您会在 4 秒内收到计时器到期的通知,而另一个线程将决定什么要做,因为主线程正在做“任务B”,没有别的可以做。

所以基本上……做不到?

哦,是的,它可以。但是您必须使“任务A”(或B,或C)特别才能工作。您必须将主线程设计为定期“等待”来自外部的事件。
并且没有很多方法可以做到这一点:定期做一些事情。你必须让你的主线程执行一个“循环”。这种模式称为运行循环。许多 UI 框架都以这种方式运行。

会发生什么:

  1. 您创建一个队列,并使其对您的程序全局可访问(例如,单例模式)。这个队列的目标是接收主线程应该执行的所有工作单元。
  2. 在启动时,您让主线程生成一个辅助线程,该辅助线程将负责在第 3 步之后继续您的应用程序的初始化过程和生命周期
  3. 让主线程进入无限循环,等待队列中的新事件

使用您的“次要”线程,您可以做任何您喜欢的事情,包括设置您的第一个计时器。当计时器触发时,它应该将要执行的工作(比如 Runnable 实例?)发送到队列。主线程将选择运行可运行的内联。

效率高吗?等待活动?

是的,可以。如果您使用为并发设计的目的良好的对象(ConcurrentQueue?),您实际上不会在等待时执行工作并浪费资源。幕后发生的事情是线程由操作系统“发出”新单元可用的“信号”。所以这不是一个无限循环,你说“有什么事情要做吗?如果是 > 做,如果不是 > 等待三秒钟”。它是“有事可做时给我发信号”。

我不知道任何 JAR / lib 或工具或最佳实践来实际实现这一点。大多数时候,要么环境提供了这个(Swing 的ìnvokeLater),要么我不需要这种东西。所以我知道这个理论上是如何工作的,但我想这很难真正实现。

此模式的维基百科条目:http://en.wikipedia.org/wiki/Event_loop.
在游戏编程中,通常会有一个“游戏循环”,这是一种等效模式

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2011-06-11
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多