📜  什么是Java Executor 框架?

📅  最后修改于: 2022-05-13 01:55:50.333000             🧑  作者: Mango

什么是Java Executor 框架?

随着当今处理器中可用内核数量的增加,再加上实现更高吞吐量的需求不断增加,多线程 API 变得越来越流行。 Java提供了自己的多线程框架,称为Java Executor Framework。

Java executor 框架(Java.util.concurrent.Executor),与JDK 5 一起发布,用于运行Runnable 对象,而无需每次都创建新线程,并且主要重用已经创建的线程。我们都知道在Java创建线程有两种方式。如果您想了解更多关于它们的比较,请阅读如何在Java创建线程。

Java.util.concurrent.Executors 提供了用于创建工作线程的 ThreadPools 的工厂方法。线程池通过保持线程处于活动状态并重用线程来克服这个问题。池中的线程可以处理的任何流入的多余任务都保存在队列中。一旦任何线程获得空闲,它们就会从该队列中选择下一个任务。对于 JDK 提供的开箱即用的执行器,此任务队列本质上是无界的。

下面列出了一些类型的Java Executor:

  1. 单线程执行器
  2. 固定线程池(n)
  3. 缓存线程池
  4. 预定执行器

让我们讨论这些流行的Java executors 的一些细节,在实现它们之前,它们究竟做了什么以获得更好的想法。



Executor 1: SingleThreadExecutor

调用Executors类的静态newSingleThreadExecutor()方法可以获得单个线程池。它用于顺序执行任务。

句法:

ExecutorService executor = Executors.newSingleThreadExecutor();

执行器 2: FixedThreadPool(n)

顾名思义,它是一个线程数量固定的线程池。提交给执行器的任务由 n 个线程执行,如果有更多任务,它们将存储在 LinkedBlockingQueue 中。它使用阻塞队列。

句法:

ExecutorService fixedPool = Executors.newFixedThreadPool(2);

Executor 3: CachedThreadPool

创建一个线程池,根据需要创建新线程,但在可用时将重用先前构造的线程。如果可用,调用 execute 将重用先前构造的线程。如果没有可用的现有线程,则会创建一个新线程并将其添加到池中。它使用 SynchronousQueue 队列。



ExecutorService executorService = Executors.newCachedThreadPool();

Executor 4: ScheduledExecutor

调度执行器基于接口 ScheduledExecutorService,它扩展了 ExecutorService 接口。当我们有一个需要定期运行的任务或者我们希望延迟某个任务时,就会使用这个执行器。

ScheduledExecutorService scheduledExecService = Executors.newScheduledThreadPool(1);
  • 可以使用以下两种方法之一来安排任务:
    • scheduleAtFixedRate :以固定的时间间隔执行任务,无论上一个任务何时结束。
    • scheduleWithFixedDelay :只有在当前任务完成后才会开始延迟倒计时。`

句法:

scheduledExecService.scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
scheduledExecService.scheduleWithFixedDelay(Runnable command, long initialDelay, long period, TimeUnit unit)

句法:

Future result = executorService.submit(callableTask);

实现:创建并执行一个简单的执行器,我们将在其中创建一个任务并在固定池中执行它

  • Task 类实现 Callable 并被参数化为 String 类型。它也被声明为抛出异常。
  • 现在为了在“Task”类中执行任务,我们必须实例化 Task 类并将其传递给执行程序以执行。
  • 打印并显示 Future 对象返回的结果

例子

Java
// Java Program demonstrating Introduction to Java Executor
// Framework
 
// Importing concurrent classes from java.util package
import java.util.concurrent.*;
 
// Class 1
// Helper Class implementing runnable interface Callable
class Task implements Callable {
    // Member variable of this class
    private String message;
 
    // Constructor of this class
    public Task(String message)
    {
        // This keyword refers to current instance itself
        this.message = message;
    }
 
    // Method of this Class
    public String call() throws Exception
    {
        return "Hiiii " + message + "!";
    }
}
// Class 2
// Main Class
// ExecutorExample
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an object of above class
        // in the main() method
        Task task = new Task("GeeksForGeeks");
 
        // Creating object of ExecutorService class and
        // Future object Class
        ExecutorService executorService
            = Executors.newFixedThreadPool(4);
        Future result
            = executorService.submit(task);
 
        // Try block to check for exceptions
        try {
            System.out.println(result.get());
        }
 
        // Catch block to handle the exception
        catch (InterruptedException
               | ExecutionException e) {
 
            // Display message only
            System.out.println(
                "Error occured while executing the submitted task");
 
            // Print the line number where exception occured
            e.printStackTrace();
        }
 
        // Cleaning resource and shutting down JVM by
        // saving JVM state using shutdown() method
        executorService.shutdown();
    }
}


输出:

Hiiii GeeksForGeeks