Executor

Executors

Executors为Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable类提供了一些工具方法,类似于集合中的Collections类的功能

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

功能:它将会为每个任务创建一个线程,此线程池的最大值是Integer的最大值(2^31-1),60秒内可以重用已经创建的线程,如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲的线程
适用:该线程池比较适合没有固定大小并且比较快速就能完成的小任务

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

功能:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,再提交新任务,任务将会进入等待队列中等待。如果某个线程因为执行异常而结束,那么线程池会补充一个新线程

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

功能:创建一个单线程的线程池。也就是相当於单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代,。此线程池保证所有任务的执行顺序按照任务的提交顺序执行

除了CachedThreadPool使用的是直接提交策略的缓冲队列以外,其余两个采用的都是无界缓冲队列

以上三种都使用ThreadPoolExecutor创建

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

 private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

corePoolSize:核心线程数量,小于corePoolSize都会直接创建线程
maximumPoolSize:最大线程数量,大于最大线程数量则由拒绝策略处理
keepAliveTime:线程最大空闲存活时间
unit:线程最大空闲存活时间单位
workQueue:缓冲队列,超过任务超过corePoolSize大小后,放入workQueue队列进行缓冲处理
threadFactory:线程工厂
defaultHandler:拒绝处理程序策略 默认AbortPolicy 抛出异常

拒绝处理程序策略

  • 默认的ThreadPoolExecutor.AbortPolicy

    处理程序遭到拒绝将抛出运行时RejectedExecutionException;

public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
  • ThreadPoolExecutor.CallerRunsPolicy

    调用excute任务本身的线程处理,主线程直接调用,如果执行程序已关闭,则会丢弃该任务

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
  • ThreadPoolExecutor.DiscardPolicy

    不能执行的任务将被删除;

  public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
  • ThreadPoolExecutor.DiscardOldestPolicy

    如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。

 public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }

        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }

ThreadFactory

默认同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态等等。

 private static class DefaultThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        DefaultThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "pool-" +
                          poolNumber.getAndIncrement() +
                         "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

ExecutorService执行方法:

  • execute(Runnable)
    这个方法接收一个Runnable实例,并且异步的执行,无法知道结果
  • submit(Runnable)
    这个方法接收一个Runnable实例,并且异步的执行,返回一个Future对象,可以检查结果
Future future = executorService.submit(new MyRunnable);
//方法会阻塞,返回null表示执行成功
future.get(); 
  • submit(Callable)
    也会返回一个Future对象,但是除此之外,submit(Callable)接收的是一个Callable的实现,Callable接口中的call()方法有一个返回值,可以返回任务的执行结果
Future future = executorService.submit(new MyCallable());
//方法会阻塞,返回值为Call()
future.get(); 

当我们使用完成ExecutorService之后应该关闭它,否则它里面的线程会一直处于运行状态。
举个例子,如果的应用程序是通过main()方法启动的,在这个main()退出之后,如果应用程序中的ExecutorService没有关闭,这个应用将一直运行。之所以会出现这种情况,是因为ExecutorService中运行的线程会阻止JVM关闭。
调用shutdown()方法之后,ExecutorService不会立即关闭,但是它不再接收新的任务,直到当前所有线程执行完成才会关闭。
调用shutdownNow()方法。这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。但是它并不对正在执行的任务做任何保证,有可能它们都会停止,也有可能执行完成。

ScheduledExecutorService

定时任务线程池

  • schedule (Runnable task, long delay, TimeUnit timeunit)
    指定延迟之后运行task。这个方法有个问题,就是没有办法获知task的执行结果。如果我们想获得task的执行结果,我们可以传入一个Callable的实例
  • schedule (Callable task, long delay, TimeUnit timeunit)
    这个方法与schedule (Runnable task)类似,也是在指定延迟之后运行task,不过它接收的是一个Callable实例,此方法会返回一个ScheduleFuture对象,通过ScheduleFuture我们可以取消一个未执行的task,也可以获得这个task的执行结果
  • scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
    周期性的调度task执行。task第一次执行的延迟根据initialDelay参数确定,以后每一次执行都间隔period时长。
    如果task的执行时间大于定义的period,那么下一个线程将在当前线程完成之后再执行。整个调度保证不会出现一个以上任务同时执行
  • scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
    与scheduleAtFixedRate类似,scheduleWithFixedDelay中,period指的当前任务的结束执行时间到下个任务的开始执行时间。
发布了15 篇原创文章 · 获赞 5 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章