tl;博士
有没有办法检查 Runnable 是否在单线程中完成?
是的。
- 通过调用
Executors.newSingleThreadScheduledExecutor 提供的ScheduledExecutorService 运行Runnable。
- 捕获返回的
ScheduledFuture 对象。
- 询问
ScheduledFuture 对象的完成状态,询问它是完成还是取消。
执行者框架
现代 Java 提供了 Executors 框架来很好地管理将任务分离到其他线程上。见tutorial by Oracle。
Executors 类(名称为复数)具有用于生成 ExecutorService 对象的工厂方法。
您希望延迟执行而不是立即执行。所以这意味着你想要一个ScheduledExecutorService。
ScheduledExecutorService scheduledExecutorService = …
您要求单线程执行。这意味着您需要一个由 thread pool 支持的执行程序,其大小为单个线程而不是多个线程。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
告诉预定的执行器服务在您想要的延迟后运行您的Runnable。调用ScheduledExecutorService::schedule 方法。
如果今天正在编写执行器框架,则延迟将表示为java.time.Duration 对象。但是 java.time 还没有被发明出来。因此,延迟表示为某个数字以及 TimeUnit 对象以指定时间粒度。你没有指定你想要的粒度,所以我会用几秒钟。
scheduledExecutorService.schedule( runnable , 10 , TimeUnit.SECONDS );
把所有这些放在一起。
Runnable runnable = ( ) -> {
System.out.println( "Running the runnable at " + Instant.now() );
};
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.schedule( runnable , 10 , TimeUnit.SECONDS ); // Wait ten seconds before running the runnable.
// Wait long enough on this `main` thread for the background thread to do its thing.
try
{
Thread.sleep( Duration.ofSeconds( 12 ).toMillis() );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
// Clean-up.
scheduledExecutorService.shutdown(); // Always shutdown your executor service when no longer needed, or when ending your app.
System.out.println( "Done at " + Instant.now() );
注意我们如何优雅地关闭执行器服务。否则,支持执行程序的线程可能会在我们的应用程序结束后无限期地像僵尸一样继续运行。
看到这个code run live at IdeOne.com。
Running the runnable at 2020-11-16T05:30:04.106661Z
Done at 2020-11-16T05:30:06.105624Z
检查完成
你问:
有什么方法可以检查 task1 是否已完成
是的。
上面看到的ScheduledExecutorService::schedule 方法返回一个ScheduledFuture 对象。我们可以查询返回的ScheduledFuture 对象的完成状态。
我们上面的代码忽略了返回的对象。让我们修改代码以捕获返回的对象。
Runnable runnable = ( ) -> {
System.out.println( "Running the runnable at " + Instant.now() );
};
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = scheduledExecutorService.schedule( runnable , 10 , TimeUnit.SECONDS ); // Wait ten seconds before running the runnable.
try
{
Thread.sleep( Duration.ofSeconds( 4 ).toMillis() ); // Wait a short while, then see if runnable completed.
System.out.println( "isDone: " + future.isDone() + " | " + "isCancelled: " + future.isCancelled() );
Thread.sleep( Duration.ofSeconds( 4 ).toMillis() ); // Wait a short while, then see if runnable completed.
System.out.println( "isDone: " + future.isDone() + " | " + "isCancelled: " + future.isCancelled() );
Thread.sleep( Duration.ofSeconds( 4 ).toMillis() ); // Wait a short while, then see if runnable completed.
System.out.println( "isDone: " + future.isDone() + " | " + "isCancelled: " + future.isCancelled() );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
// Clean-up.
scheduledExecutorService.shutdown();
System.out.println( "Done at " + Instant.now() );
运行时。
isDone: false | isCancelled: false
isDone: false | isCancelled: false
Running the runnable at 2020-11-16T05:44:07.803125Z
isDone: true | isCancelled: false
Done at 2020-11-16T05:44:09.821267Z