【问题标题】:In Java, is there a way to check if Runnable is completed in single thread?在 Java 中,有没有办法检查 Runnable 是否在单线程中完成?
【发布时间】:2021-02-18 02:41:18
【问题描述】:

在Java中,我需要以毫秒为单位获取Runnable和Delay两个参数,并且需要在延迟时间内运行Runnable。这需要在单线程中运行,并且如果使用不同的参数值调用方法并且之前的任务还没有完成,则应该将其保留在队列中。

public void runScheduledTask(Runnable task, long delay) {
   // ...
}

...

runScheduledTask(task1, 10); // at 00:00:00.000
runScheduledTask(task2, 10); // at 00:00:00.005

当使用task2调用该方法时,由于延迟10,task1尚未启动/完成,因此应将task2存储在队列中。 在这种情况下,有没有办法可以检查 task1 是否已完成? 由于这应该在当前线程中运行,我不知道我可以使用哪些类或工具。

【问题讨论】:

标签: java multithreading runnable single-threaded


【解决方案1】:

tl;博士

有没有办法检查 Runnable 是否在单线程中完成?

是的。

  1. 通过调用Executors.newSingleThreadScheduledExecutor 提供的ScheduledExecutorService 运行Runnable
  2. 捕获返回的ScheduledFuture 对象。
  3. 询问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

【讨论】:

    猜你喜欢
    • 2018-08-02
    • 2021-02-13
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2020-04-13
    • 2013-07-23
    • 2012-06-30
    相关资源
    最近更新 更多