SingleThreadScheduledExecutor 是如何工作的?
它创建一个最多包含一个线程的线程池。这确保一次只有一个任务(在这个执行程序上安排)将运行。
任务在执行者的单线程中运行,而不是在提交它们的线程上。
你能让这个方法在“主线程”上运行吗?*
那么你可以“制造”任何东西,对吧?但不是与 ExecutorService 一起使用,它旨在与自己的线程一起工作。
那又如何呢?
基本上,要么您处于为您提供一切的环境中(例如 Swing 中的 UI 应用程序),所以请检查您的情况是否如此(Swing 具有事件调度线程)。要么你需要一些工作。所以我首先建议你确保在继续做这项工作之前你真的需要在主线程中工作。
这项工作涉及什么?
无需任何特殊工作,您的主线程就会执行不可中断的语句流代码。它们只写一次,没有人可以将代码“注入”到你的主线程中(好吧,除非你的记忆真的很乱,你可以这样做,但这不是人们通常会做的事情)。
因此,您的主线程正忙于按顺序执行任务 A,然后是 B,然后是 C,然后是 D,尽可能快(或被允许)。您不能在此流程中间注入“任务 E”。
打个比方,这相当于在代码中随机选择一行,并在此处添加另一个方法的语句:保证崩溃(上下文是什么,堆栈是什么,该特定行中存在哪些变量,以及使用哪个值: 不可预测)。这不可能发生。
因此,即使任务 A 是“创建一个要在 4 秒内执行的任务”,将会发生的情况是:在另一个线程中,您会在 4 秒内收到计时器到期的通知,而另一个线程将决定要做什么,因为主线程正在执行“任务B”,它无能为力。
所以基本上......它不能完成?
哦,是的,它可以。但是您必须使“任务A”(或B,或C)特别才能工作。您必须将主线程设计为定期“等待”来自外部的事件。
并且没有很多方法可以做到这一点:定期做一些事情。你必须让你的主线程执行一个“循环”。这种模式称为运行循环。许多许多 UI 框架都以这种方式运行。
会发生什么:
- 您创建一个队列,并使其对您的程序全局可访问(例如,单例模式)。这个队列的目标是接收主线程应该执行的所有工作单元。
- 启动时,您使主线程产生一个辅助线程,该辅助线程将负责在第 3 步之后继续初始化过程和应用程序的生命周期
- 你让你的主线程进入一个无限循环,等待队列中的新事件
使用您的“辅助”线程,您可以做任何您喜欢的事情,包括设置您的第一个计时器。当计时器触发时,它应该将要执行的工作(比如 Runnable 实例?)发送到队列。主线程将选择运行可运行的内联。
那效率高吗?等待事件?
是的,可以。如果您使用为并发设计的目的良好的对象 ( ConcurrentQueue
?),您实际上不会在等待时执行工作并浪费资源。幕后发生的事情是线程由操作系统“发出”新单元可用的“信号”。所以这不是一个无限循环,你说“有什么事情要做吗?如果是 > 做,如果不是 > 等待三秒钟”。它是“有事可做时给我发信号”。
我不知道任何 JAR / lib 或工具或最佳实践来实际实现这一点。大多数时候,要么环境提供了这个(Swing's ìnvokeLater
),要么我不需要这种东西。所以我知道这在理论上是如何工作的,但我想这很难真正实现。
这种模式的维基百科条目:http ://en.wikipedia.org/wiki/Event_loop 。
在游戏编程中,通常有一个“游戏循环”,它是一种等效模式