Java多线程编程--线程池

  在计算机中,线程是稀缺资源,创建过多的线程,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配、调优和监控,有以下好处:

  • 降低资源消耗;
  • 提高响应速度;
  • 提高线程的可管理性。

  Java多线程编程常用到多线程框架Executor,使用此框架可以方便、高效的对线程进行管理,我们先了解下Executor。
  Executor是从Java 5开始引入的一个框架,在java.util.concurrent 包下,其内部使用了线程池机制,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,更方便管理,效率更高。
  Executor框架主要包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future/FutureTask,Runnable/Callable等。

Executor接口

  Executor接口是Executor框架最基本的接口,Executor框架的大部分类都直接或间接地实现了此接口。Executor接口只有一个方法:

void execute(Runnable command);

  该方法接收一个Runable实例参数,用来执行一个任务,这个任务就是一个实现了Runnable接口的类。

ExecutorService接口

  ExecutorService接口继承自Executor接口,它提供了多个方法用于对线程进行管理。

public interface ExecutorService extends Executor {
    //依次关闭任务,在此过程中会执行先前提交的任务,但不接受任何新任务。
    void shutdown();
    
    //阻止等待中的任务启动,并试图停止当前正在执行的任务,不再接收新任务,返回处于等待队列的任务列表
    List<Runnable> shutdownNow();

    //判断线程池是否已经关闭
    boolean isShutdown();

    //如果执行关闭操作后所有任务都已完成,则返回true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
    boolean isTerminated();

    //阻塞并等待被关闭任务执行完成,或发生超时,或发生中断  
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    //提交一个有返回值的 Callable 任务用于执行,并返回一个表示任务的未决结果的Future。任务成功执行时,该Future的get()方法将会返回执行结果。
    <T> Future<T> submit(Callable<T> task);

    //提交一个 Runnable 任务用于执行,并返回一个表示该任务的Future。任务成功执行时,该Future的get()方法将会返回给定的结果 result。
    <T> Future<T> submit(Runnable task, T result);

    //提交一个 Runnable 任务用于执行,并返回一个表示该任务的Future。任务成功执行时,该Future的get()方法将会返回null   
    Future<?> submit(Runnable task);

    //执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

    //执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。
    <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;
}

Executors类

  Executors是Java线程池的工厂类,它提供了一系列方法用于创建线程池,返回的线程池都实现了ExecutorService接口。 

  常用的创建线程池的方法:

public static ExecutorService newSingleThreadExecutor();

  创建一个单线程的线程池。这个线程池用唯一的工作线程来执行任务,所有任务按照指定顺序依次执行。

public static ExecutorService newFixedThreadPool(int nThreads);

  创建具有固定的线程数量的线程池。线程池中的这些线程可重用,当所有线程都处于活动状态时,再次提交的任务都会加入等待队列,等待其他线程结束,当有线程处于空闲状态时会被下一个任务复用。

public static ExecutorService newCachedThreadPool();

  创建一个可缓存线程的线程池,调用execute()将重用以前构造的线程(如果有线程可用)。如果当前没有线程可用,则创建一个新线程并添加到线程池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
可以看出缓存线程池大小是不定值,根据需要会创建不同数量的线程。在使用缓存型线程池时,先查看线程池中有没有空闲线程,如果有,就复用;如果没有,新建线程并加入线程池中。缓存型线程池通常用于执行一些生存期很短的异步型任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);

  创建一个支持定时及周期性任务执行的线程池。此线程池中的线程可延迟执行,定时执行或固定周期执行。

CompletionService

Runnable/Callable

  实现了Runnable或Callable接口的类就是线程的执行类,线程业务代码要被封装在实现了Runnable或Callable接口的类中。实现了Runnable接口的线程业务类可以使用execute()方法直接执行,也可以使用ExecutorService的submit()方法提交并执行。实现了Callable接口的线程业务类,只能通过ExecutorService的submit(Callable task) 方法来提交并执行,并且返回一个Future,这个Future表示任务的未决执行结果。

线程池

  表示线程池的类有两个:ThreadPoolExecutor 和 ScheduledThreadPoolExecutor,Executors类创建的线程池就属于这两个类中的一个。

  ThreadPoolExecutor:单线程线程池、可缓存的线程池、固定数目线程的线程池都是ThreadPoolExecutor类。
  ScheduledThreadPoolExecutor: 支持定时及周期性的任务的线程池是ScheduledThreadPoolExecutor类。

示例

   待补充

参考:

  https://blog.csdn.net/fangqun663775/article/details/78961417
  https://www.cnblogs.com/fengsehng/p/6048610.html
  https://blog.csdn.net/tongdanping/article/details/79604637

猜你喜欢

转载自www.cnblogs.com/leaves1024/p/11251232.html