2021-04-18 11:26  阅读(100)
文章分类:Java 基础教程 文章标签:JavaJava 教程
©  原文作者:w3cschool 原文地址:https://www.w3cschool.cn/java/java-thread-multiple.html

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();
      }
    }
    

上面的代码生成以下结果。20210418112118_1.png

结果承载任务

要在任务完成时获取任务的结果,请使用Callable接口的实例。

类型参数V是任务的结果的类型。

Callable接口有一个call()方法。它可以返回任何类型的值。

它允许你抛出异常。它声明如下:

    public interface  Callable<V>  {
        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<Integer> {
      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<Integer> submittedTask = exec.submit(task);
    
        Integer result = submittedTask.get();
        System.out.println("Task"s total  sleep time: " + result + "  seconds");
        exec.shutdown();
      }
    }
    

上面的代码生成以下结果。

2021041811216_2.png

调度任务

执行器框架允许您计划将来运行的任务。

    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();
      }
    }
    

上面的代码生成以下结果。

202104181128_3.png

在任务执行中处理未捕获的异常

执行器框架在任务执行期间处理任何未捕获异常的事件。

如果使用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();
      }
    }
    

上面的代码生成以下结果。

202104181127_4.png

在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<Object> 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();
      }
    }
    

202104181127_5.png

执行完成服务

要将提交的任务的结果提供给执行程序,请使用执行程序的完成服务。

它由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<MyResult> {
      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<MyResult> 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<MyResult> completedTask = completionService.take();
          MyResult result = completedTask.get();
          System.out.println("Completed a  task - " + result);
        }
        exec.shutdown();
      }
    }
    

上面的代码生成以下结果。

202104181127_6.png

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Java 执行器
上一篇
Java 同步器
下一篇
Java Fork/Join框架