Java多线程—Executor框架

1. 任务Task相关的接口与类

1.1 Runnable

表示一个可被执行的命令,通常用于在不同线程中执行任务。

package java.lang;

public interface Runnable {
    public void run();
}

1.2 Callable<V>

表示一个有返回结果的任务

package java.util.concurrent;

public interface Callable<V> {
    V call() throws Exception;
}

1.3 Future<V>

表示一个异步任务的结果。Executor.execute(Runnable)会返回一个Future。调用Future.get()会阻塞当前线程,直至任务完成返回结果。

package java.util.concurrent;

public interface Future<V> {

    /**
     * 取消任务的执行。
     * 以下几种情况不能成功取消任务:
     * 1.任务已完成。 2.任务已经被取消。 3.任务因为某些原因不能被取消。
     *
     * 如果成功过,任务将不会执行。
     * 如果任务已经启动,参数mayInterruptIfRunning将决定执行任务线程是否应该被中断,已达到停止任务的目的。
     *
     * 该方法返回后,isDone()将总是返回true。
     * 如果该方法返回true,isCanelled()将返回true。
     */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * 返回true表示任务在完成前被取消。
     */
    boolean isCancelled();

    /**
     * 返回true表示任务完成
     *
     * 任务完成可能原因如下:
     * 1.正常执行完成 2.异常 3.被取消
     */
    boolean isDone();

    /**
     * 等待任务的完成,并返回结果,。
     *
     * @return 返回任务执行结果
     * @throws CancellationException 当任务被取消时
     * @throws ExecutionException 当任务执行出现异常时
     * @throws InterruptedException 等待过程中线程被中断时
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * 在指定时间内等待任务的完成,并返回结果。
     *
     * @param 等待超时最长时间
     * @param 时间单位
     * @return 返回任务执行结果
     * @throws CancellationException 当任务被取消时
     * @throws ExecutionException 当任务执行出现异常时
     * @throws InterruptedException 等待过程中线程被中断时
     * @throws TimeoutException 等待超时
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

1.4 RunnableFuture<V>

该接口继承于Runnable和Future。

package java.util.concurrent;

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

1.5 FutureTask<V>

一个可以取消的异步任务。该类实现了RunnableFuture接口。

2. Executor框架

2.1 Executor

Executor负责执行提交的Runnable任务。这个接口提供了一种将任务提交和任务执行解耦的机制。Executor通常用于代替显示创建线程。

package java.util.concurrent;

public interface Executor {
    void execute(Runnable command);
}

2.2 ExecutorService

该接口继承于Executor接口。提供了管理线程池生命周期的方法和提交任务的便利方法。常用的具体的实现有ThreadPoolExecutor、ScheduledThreadPoolExecutor等。

public interface ExecutorService extends Executor {

    void shutdown();

    List<Runnable> shutdownNow();

    boolean isShutdown();

    boolean isTerminated();

    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    <T> Future<T> submit(Callable<T> task);

    <T> Future<T> submit(Runnable task, T result);

    Future<?> submit(Runnable task);

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;

    <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException;

    <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

2.3 Executors

Executors为一个静态工厂,用于生产Executor、ExecutorService、ScheduledExecutorService、ThreadFactory和Callable。

package java.util.concurrent;

public class Executors {

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public static ThreadFactory defaultThreadFactory() {
        return new DefaultThreadFactory();
    }

    public static ThreadFactory privilegedThreadFactory() {
        return new PrivilegedThreadFactory();
    }

    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }

    public static Callable<Object> callable(Runnable task) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<Object>(task, null);
    }

    /** Cannot instantiate. */
    private Executors() {}
}

3. UML类图

这里写图片描述

4. 线程池

线程池的优点:
1. 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
2. 能有效控制线程池的最大并发数,避免大量的线程之间因为互相抢占系统资源而导致的阻塞现象。
3. 能够对线程进行管理,并提供定时的执行以及指定间隔循环执行等功能。

4.1 ThreadPoolExecutor

线程池的真正实现为ThreadPoolExecutor,其构造方法如下:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

参数含义
int corePoolSize
线程池的核心线程数,默认情况下,核心线程还在线程池中一直存活,即使处于闲置状态。
若ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程会超时,这个时间间隔有参数keepAliveTime决定,闲置等待任务超过keepAliveTime时间后,核心线程就会被终止。

int maximumPoolSize
线程池所能容纳的最大线程数。
当活动线程达到这个值后,后续新的任务将被阻塞。

long keepAliveTime
非核心线程闲置时间超过keepAliveTime将被回收。
若allowCoreThreadTimeOut为true,则核心线程超时也会被回收。

TimeUnit unit
keepAliveTime的时间单位。TimeUnit为一个枚举类型,有TimeUnit.MILLISECONDS、TimeUnit.SECONDS以及TimeUnit.MINUTES等。

BlockingQueue workQueue
线程池中的任务队列,通过线程池的execute方法提交的Runnable对象将会存储在这个参数中。

ThreadFactory threadFactory
线程工厂,为线程池创建新线程。

public interface ThreadFactory {
    Thread newThread(Runnable r);
}

RejectedExecutionHandler handler
当线程池无法执行新任务时,这可能由于队列已满或是无法成功执行任务,ThreadPoolExecutor会调用handler的rejectedException方法。默认情况下抛出RejectedExecutionException。ThreadPoolExecutor为handler提供了几个可选值:CallerRunsPolicy、AbortPolicy(默认handler)、DiscardPolicy、DiscardOldestPolicy。该参数不常用。

4.2 线程池执行任务的规则

  1. 若线程池中的线程数量 < 核心线程数量,那么会创建一个核心线程来执行任务。
  2. 若线程池中的线程数量 >= 核心线程数量,那么任务将会被插入到任务队列中排队等待执行。
  3. 若因为队列已满,任务无法插入到任务队列中,若此时线程数量< 线程池最大线程数,那么会创建一个非核心线程来执行任务。
  4. 若线程数量 > 线程池最大线程数,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。

4.3 线程池类型

以下的线程池创建方法都在Executors类中。

4.3.1 FixedThreadPool
创建方法

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

任务队列为LinkedBlockingQueue,无界队列。
仅有核心线程,并且核心线程没有超时机制,即不会被回收,所以可以更快地响应外界的请求。

4.3.2 SingleThreadExecutor
创建方法

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

一个核心线程,确保所有任务在同一个线程中顺序执行。

4.3.3 CachedThreadPool
创建方法

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

任务队列为SynchronousQueue。SynchronousQueue的每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。所以每当执行一个任务, CachedThreadPool都要为该任务及时提供一个进程,要么新创建,要么使用闲置线程。
核心线程数为0,非核心线程数为Integer.MAX_VALUE。
线程闲置超时时间为60s。
比较适合执行大量的耗时较少的任务。

4.3.4 ScheduledThreadPool
创建方法

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

核心线程数固定,非核心线程数为Integer.MAX_VALUE。
线程闲置超时时间为0,则当非核心线程闲置时会被立即回收。主要用于执行定时任务和具有固定周期的重复任务。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值