Java线程教程 - Java执行器
框架提供了一种将任务提交与任务执行分离的方法。
java.util.concurrent包中的Executor接口是执行器框架的基础。
它是一个只有一个方法的接口,如图所示:public interface Executor {
void execute (Runnable command);
}import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class RunnableTask implements Runnable {
private int taskId;
private int loopCounter;
public RunnableTask(int taskId, int loopCounter) {
this.taskId = taskId;
this.loopCounter = loopCounter;
}
public void run() {
for (int i = 1; i <= loopCounter; i++) {
try {
System.out.println("Task #" + this.taskId + " - Iteration #" + i);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Task #" + this.taskId
+ " has been interrupted.");
break;
}
}
}
}
public class Main {
public static void main(String[] args) {
final int THREAD_COUNT = 3;
final int LOOP_COUNT = 3;
final int TASK_COUNT = 5;
// Get an executor with three threads in its thread pool ExecutorService exec = Executors.newFixedThreadPool(THREAD_COUNT);
// Create five tasks and submit them to the executor for (int i = 1; i <= TASK_COUNT; i++) {
RunnableTask task = new RunnableTask(i, LOOP_COUNT);
exec.submit(task);
}
exec.shutdown();
}
}
上面的代码生成以下结果。
结果承载任务
要在任务完成时获取任务的结果,请使用Callable接口的实例。
类型参数V是任务的结果的类型。
Callable接口有一个call()方法。它可以返回任何类型的值。
它允许你抛出异常。它声明如下:public interface Callable {
V call() throws Exception;
}import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class CallableTask implements Callable {
private int taskId;
public CallableTask(int taskId) {
this.taskId = taskId;
}
public Integer call() throws InterruptedException {
int total = taskId;
try {
System.out.println("Task #" + this.taskId);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Task #" + this.taskId
+ " has been interupted.");
throw e;
}
total+=taskId;
return total;
}
}
public class Main {
public static void main(String[] args) throws Exception {
// Get an executor with three threads in its thread pool ExecutorService exec = Executors.newFixedThreadPool(3);
CallableTask task = new CallableTask(1);
// Submit the callable task to executor Future submittedTask = exec.submit(task);
Integer result = submittedTask.get();
System.out.println("Task"s total sleep time: " + result + " seconds");
exec.shutdown();
}
}
上面的代码生成以下结果。
调度任务
执行器框架允许您计划将来运行的任务。import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
class ScheduledTask implements Runnable {
private int taskId;
public ScheduledTask(int taskId) {
this.taskId = taskId;
}
public void run() {
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("Task #" + this.taskId + " ran at "
+ currentDateTime);
}
}
public class Main {
public static void main(String[] args) {
// Get an executor with 3 threads ScheduledExecutorService sexec = Executors.newScheduledThreadPool(3);
ScheduledTask task1 = new ScheduledTask(1);
ScheduledTask task2 = new ScheduledTask(2);
// Task #1 will run after 2 seconds sexec.schedule(task1, 2, TimeUnit.SECONDS);
// Task #2 runs after 5 seconds delay and keep running every 10 seconds sexec.scheduleAtFixedRate(task2, 5, 10, TimeUnit.SECONDS);
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
sexec.shutdown();
}
}
上面的代码生成以下结果。
在任务执行中处理未捕获的异常
执行器框架在任务执行期间处理任何未捕获异常的事件。
如果使用Executor对象的execute()方法执行Runnable任务,任何未捕获的运行时异常将停止任务执行,并且异常堆栈跟踪将打印在控制台上。import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Runnable badTask = () -> {
throw new RuntimeException(
"Throwing exception from task execution...");
};
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(badTask);
exec.shutdown();
}
}
上面的代码生成以下结果。
在Callable任务中处理异常
以下代码显示了如何在Callable任务中处理异常。import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) {
Callable badTask = () -> {
throw new RuntimeException(
"Throwing exception from task execution...");
};
ExecutorService exec = Executors.newSingleThreadExecutor();
Future submittedTask = exec.submit(badTask);
try {
Object result = submittedTask.get();
} catch (ExecutionException e) {
System.out.println(e.getMessage());
System.out.println(e.getCause().getMessage());
} catch (InterruptedException e) {
e.printStackTrace();
}
exec.shutdown();
}
}
执行完成服务
要将提交的任务的结果提供给执行程序,请使用执行程序的完成服务。
它由CompletionService接口的一个实例表示。import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyResult {
private int taskId;
private int result;
public MyResult(int taskId, int result) {
this.taskId = taskId;
this.result = result;
}
public int getTaskId() {
return taskId;
}
public int getResult() {
return result;
}
public String toString() {
return "Task Name: Task #" + taskId + ", Task Result:" + result
+ " seconds";
}
}
class SleepingTask implements Callable {
private int taskId;
private int loopCounter;
public SleepingTask(int taskId, int loopCounter) {
this.taskId = taskId;
this.loopCounter = loopCounter;
}
public MyResult call() throws InterruptedException {
int totalSleepTime = 0;
for (int i = 1; i <= loopCounter; i++) {
try {
System.out.println("Task #" + this.taskId + " - Iteration #"
+ i);
Thread.sleep(1000);
totalSleepTime = totalSleepTime + 1000;
} catch (InterruptedException e) {
System.out.println("Task #" + this.taskId
+ " has been interupted.");
throw e;
}
}
return new MyResult(taskId, totalSleepTime);
}
}
public class Main {
public static void main(String[] args) throws Exception {
// Get an executor with three threads in its thread pool ExecutorService exec = Executors.newFixedThreadPool(3);
// Completed task returns an object of the TaskResult class ExecutorCompletionService completionService = new ExecutorCompletionService<>(
exec);
for (int i = 1; i <= 5; i++) {
SleepingTask task = new SleepingTask(i, 3);
completionService.submit(task);
}
for (int i = 1; i <= 5; i++) {
Future completedTask = completionService.take();
MyResult result = completedTask.get();
System.out.println("Completed a task - " + result);
}
exec.shutdown();
}
}
上面的代码生成以下结果。