有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java实现Runnable的类被认为是ExecutorServices的“Runnable任务”?

我正在尝试使用执行器而不是同步方法来为我管理线程。但是submit方法采用的是Runnable task而不是真正的Runnable target,这就是我想要的,因为我正在启动一个线程,目标类将被实例化并运行,如下所示:

        thread = new Thread(this, "thread-process");
        thread.start();

我试着对遗嘱执行人做一些类似的事情:

        this.exec = Executors.newSingleThreadExecutor();
        this.exec.submit(this);

据我所知,线程似乎启动和运行良好,但我不确定这些是否是等效的?在使用Executors时,这是我处理可运行目标线程的方式吗


共 (1) 个答案

  1. # 1 楼答案

    tl;博士

    • 是的,这两种方法达到了相同的目的:一些代码在后台线程上执行
    • 使用第二个(Executors框架)而不是显式的Thread实例化
    • 不要挂断持有Runnable对象引用的变量的名称

    细节

    是的,给定一个^{}(一个带有^{}方法的对象)如下:

    public class ReportRunnable implements Runnable {
    
        public void run() {
            System.out.println( "Reporting at " + Instant.now() );  // Passing: ( Runnable target , String name ).
        }
    
    }
    

    …然后这样做:

    Runnable runnable = new ReportRunnable() ;
    thread = new Thread( runnable , "thread-process" );
    thread.start();
    

    …实际上与这样做是一样的:

    ExecutorService executorService = Executors.newSingleThreadExecutor() ;
    … // You should be keeping a reference to the executor service, so that you can later shut it down gracefully.
    Runnable runnable = new ReportRunnable() ;
    executorService.submit( runnable ) ;
    

    在这两种情况下,您都会立即启动一些在后台线程上执行的工作。所以从这个意义上说,它们具有相同的效果。但也有重要的区别

    要知道,Executors框架(参见Tutorial by Oracle)的发明是为了让大多数场景中的大多数程序员不必掌握管理线程的艺术。所以你几乎不再需要自己实例化Thread。尽可能使用executor框架

    一个区别是executor服务的^{}方法返回一个^{}对象。在上面的代码中,我们忽略了这个返回的对象。但是,您可能希望捕获对该对象的引用,以便以后查看任务的进度或完成状态

    另一个区别是,您可以选择从单个线程切换到使用由executor服务自动管理的线程池。在某些情况下,您可能希望一组任务共享同一个线程池。executor服务使这变得非常简单

    ExecutorService executorService = Executors.newFixedThreadPool​( 3 )
    

    )

    executor为您提供的各种服务有很大的不同。您可以安排任务在经过一定时间后运行,而不是立即运行。你可以重复执行一项任务,比如每小时发送一封状态报告电子邮件

    ScheduledExecutorService ses = newSingleThreadScheduledExecutor() ;
    … // You should be keeping a reference to the executor service, so that you can later shut it down gracefully.
    Runnable runnable = new ReportRunnable() ;
    ScheduledFuture<?> reportFuture = scheduler.scheduleAtFixedRate( runnable , 0 , 2 , TimeUnit.HOURS ) ;
    

    另一个区别是管理线程终止,如下所述

    变量名是不相关的

    你说:

    But the submit method takes a Runnable task and not really a Runnable target

    你似乎对变量命名很感兴趣变量命名与此处无关^{} constructor Javadoc使用target,如我在run方法中的注释中粘贴的副本所示。然而,我选择了一个名为runnable的变量。你可以选择像exportQuarterlySalesDataRunnabletasktargetpinkElephant这样的名字

    终止线程

    请注意,最终需要终止线程。在应用程序运行期间,您可能不再需要该线程或其当前正在执行的工作。或者你的应用程序可能正在结束运行,在这种情况下,你必须关闭你的线程,或者在你的应用程序停止后,让它们继续像僵尸一样运行

    executor服务通过几个shutdown…方法使线程终止变得容易。您可以选择中断正在进行的任何当前工作,或等待任何当前工作完成

    Lambda语法

    为了完整起见,我将提到,通过现代Java中添加的lambda特性,可以使用更短的语法


    必读小贴士:阅读、重读、再读布莱恩·戈茨等人的优秀著作Java Concurrency in Practice