在Java代码中,ExecutorService.submit和ExecutorService.execute之间有什么区别?

13 浏览
0 Comments

在Java代码中,ExecutorService.submit和ExecutorService.execute之间有什么区别?

我正在学习使用ExectorService来管理线程并发送任务。下面是一个简单的程序示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Processor implements Runnable {
    private int id;
    public Processor(int id) {
        this.id = id;
    }
    public void run() {
        System.out.println("Starting: " + id);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            System.out.println("抱歉,被中断了,再见!");
            System.out.println("Interrupted " + Thread.currentThread().getName());
            e.printStackTrace();
        }
        System.out.println("Completed: " + id);
    }
}
public class ExecutorExample {
    public static void main(String[] args) {
        Boolean isCompleted = false;
        ExecutorService executor = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 5; i++) {
            executor.execute(new Processor(i));
        }
        //executor不再接受任何新任务,但已提交的任务会继续执行
        executor.shutdown();
        System.out.println("所有任务已提交。");
        try {
            //等待exectutor正常终止,如果超时则返回false,但不会中断线程
            isCompleted = executor.awaitTermination(100, TimeUnit.SECONDS);
            //这将中断executor管理的线程。在线程中捕获中断异常
            //否则,线程将一直运行,executor将无法关闭。
            executor.shutdownNow();
        } catch (InterruptedException e) {
        }
        if (isCompleted) {
            System.out.println("所有任务已完成。");
        } else {
            System.out.println("超时 " + Thread.currentThread().getName());
        }
    }
}

这段代码并没有什么特别的,它创建了两个线程并提交了总共5个任务。每个线程完成其任务后,它会执行下一个任务。

在上面的代码中,我使用了executor.submit,我也尝试了executor.execute,但是在输出结果中我没有看到任何区别。那么submitexecute方法有什么不同呢?

这是API中的解释:

通过创建并返回一个Future,方法submit扩展了基本方法Executor.execute(java.lang.Runnable),可以用于取消执行和/或等待完成。方法invokeAny和invokeAll执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成。(可以使用ExecutorCompletionService类来编写这些方法的定制变体。)

但是我不清楚它到底是什么意思?

0
0 Comments

在Java中,ExecutorService是一个接口,用于管理和执行线程池中的任务。在ExecutorService接口中,有两个常用的方法:submit()和execute(),它们的作用是将任务提交给线程池进行执行。然而,它们之间存在一些差异。

首先,submit()方法用于提交任务并返回一个Future对象,可以用来取消任务的执行或者等待任务的完成。而execute()方法则只是简单地提交任务,不返回任何结果。

其次,submit()方法对于未处理的异常进行了封装,而execute()方法会抛出未处理的异常。这意味着,如果使用submit()方法提交的任务发生异常,可以通过Future对象获取异常信息;而如果使用execute()方法提交的任务发生异常,需要在代码中显式处理异常。

针对使用submit()方法处理异常的情况,有几种解决方法:

1. 将Callable或Runnable代码块放在try{} catch{}块中进行处理。

2. 将future.get()方法调用放在try{} catch{}块中进行处理。

3. 自定义ThreadPoolExecutor类,并重写afterExecute方法来处理异常。

需要注意的是,使用Future.get()方法会将异步执行转换为同步执行,并丧失异步执行的好处。如果业务用例涉及异步事件处理,并且期望在X秒内响应,可以对Future操作设置超时。

关于其他问题,关于invokeAll()方法和invokeAny()方法的作用如下:

invokeAll()方法会执行给定的任务,并在所有任务完成或超时到期时返回一个包含任务状态和结果的Future列表。

invokeAny()方法会执行给定的任务,并返回一个已成功完成的任务(即未抛出异常),如果在给定的超时时间内有任何任务成功完成。

如果想等待所有提交的任务完成,可以使用invokeAll()方法。如果只希望在N个提交的任务中的一个成功完成,可以使用invokeAny()方法。在这种情况下,如果有一个任务成功完成,那么正在进行的其他任务将被取消。

需要注意的是,submit()方法并没有“隐藏”异常,而是在调用get()方法时将异常封装在ExecutionException中抛出。可以通过ExecutionException.getCause()方法获取原始异常。

submit()方法和execute()方法在异常处理和返回结果方面存在差异。根据具体的业务需求,可以选择适合的方法来提交任务并处理异常。

0
0 Comments

在Java中,ExecutorService.submit和ExecutorService.execute之间的区别是什么?

在这段代码中,execute方法只是简单地启动任务而不做任何其他操作,而submit方法则返回一个Future对象来管理任务。您可以使用Future对象执行以下操作:

  • 使用cancel方法提前取消任务。
  • 使用get方法等待任务执行完成。

如果您向线程池提交一个Callable对象,那么Future接口会更有用。当调用Future.get时,call方法的返回值将被返回。如果您不保留对Future的引用,没有区别。

不,execute()方法的规范说明了“在将来的某个时间执行给定的命令”。因此,它不一定会立即开始执行。区别在于您不关心它什么时候执行或者检查结果或完成状态。

原因:

在Java中,ExecutorService是一个框架,用于管理和执行线程池中的任务。ExecutorService接口提供了两种方法来提交任务:submit和execute。这两种方法在功能上有所不同,因此需要理解它们之间的区别。

解决方法:

要理解ExecutorService.submit和ExecutorService.execute之间的区别,需要知道它们的不同用途和返回值。

ExecutorService.submit方法用于提交任务并返回一个Future对象。Future对象用于管理任务的执行状态和结果。通过Future对象,可以取消任务、等待任务执行完成,并获取任务的执行结果。

ExecutorService.execute方法用于提交任务并立即启动执行,但它不返回任何结果或状态信息。如果不关心任务的执行结果或状态,可以使用execute方法。

通过理解这两种方法的区别,可以根据具体需求选择适当的方法来提交任务并管理任务的执行。

0
0 Comments

在Java中,ExecutorService接口提供了两种执行任务的方法:submit和execute。这两种方法之间的区别在于返回值和异常处理。

首先,根据JavaDoc的说明,execute(Runnable)方法不返回任何值。而submit(Callable)方法返回一个Future对象,该对象允许您在以后编程方式取消正在运行的线程,并在Callable完成时获取返回的T值。如果想要了解更多细节,可以查阅JavaDoc中Future的说明。

另外,如果future.get() == null并且没有抛出任何异常,则表示Runnable成功执行。这意味着任务正常完成,没有出现异常。

另一个区别是,如果使用execute(...)方法运行的任务抛出异常,线程将被终止并可能由ExecutorService重新启动。这意味着如果任务发生异常,线程将被重新启动以继续执行其他任务。

此外,还需要注意的是,一旦线程开始执行任务,就无法取消任务。尽管可以中断正在运行任务的线程,但任务本身无法被取消。

ExecutorService的submit和execute方法在返回值和异常处理方面有所不同。如果需要获取任务的返回值或者在任务执行过程中进行取消操作,应该使用submit方法;如果只需要执行任务而不关心返回值,且希望在任务抛出异常时重新启动线程,可以使用execute方法。

0