java线程(四)

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」@[toc]

六.四个常用的线程池:

①.Executors

使用:package java.util.concurrent 中的 Executors类,通过Executors类的静态方法,可以创建出我们常用的几个线程池;
复制代码

②.使用Executors创建线程池

1.cachedThreadPool

可缓存线程池

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
​
    
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }
复制代码

可以看到发生了重载,第二个方法里加入了参数ThreadFactory

使用时:

ExecutorService CachedThreadPool = Executors.newCachedThreadPool();
ExecutorService CachedThreadPool = Executors.newCachedThreadPool(threadFactory);
复制代码

根据我们上面对ThreadPoolExecutor类的分析,这里是返回了一个

corePoolSize为0,maximumPoolSize(池中允许的最大线程数)为2^31-1个,keepAliveTime(空闲线程等待时间)为60秒,创建一个非公平竞争的队列

2.FixedThreadPool

可重用固定个数的线程池

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
​
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
复制代码

可以看到发生了重载,第二个方法里加入了参数ThreadFactory

使用时:

ExecutorService FixedThreadPool = Executors.newFixedThreadPool(int);
ExecutorService FixedThreadPool = Executors.newFixedThreadPool(int,threadFactory);
复制代码

根据我们上面对ThreadPoolExecutor类的分析,这里是返回了一个

corePoolSize和maximumPoolSize(池中允许的最大线程数)的个数都为传入的nThreads值,keepAliveTime(空闲线程等待时间)为0毫秒,创建一个容量为2^31-1大小的Lind阻塞队列

3.ScheduledThreadPool

创建一个线程池,该线程池可以安排命令在给定延迟后运行或定期执行。@param corePoolSize保留在线程池中的线程数,即使它们是空闲的

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
复制代码

使用时:(demo)

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
        /**
        * 创建并执行在给定延迟后启用的一次性操作
        */
        scheduledExecutorService.schedule(new Runnable() { 
            @Override
            public void run() {
                System.out.println("10秒延迟结束");
            }
        },10,TimeUnit.SECONDS);
        /**
        *创建并执行一个周期性动作,该动作在给定的初始延迟之后首先启用,然后在给定的周期之后启用;即执行将在{@code initialDelay}之后开始,然后是{@code         *initialDelay+period},然后是{@code initialDelay+ 2 period},以此类推。如果任务的任何执行遇到异常,则禁止后续执行。否则,任务只能通过取          *消或终止执行器来终止。如果该任务的任何执行花费的时间超过了它的周期,那么后续执行可能会延迟开始,但不会并发执行。
        */
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                {任务}
            }
        },1,3,TimeUnit.SECONDS);
复制代码

4.SingleThreadExecutor

创建一个Executor,该Executor使用一个工作线程操作一个无界队列。任务保证按顺序执行(但是请注意,如果这个线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,将会有一个新的线程代替它。),与等价的{@code newFixedThreadPool(1)}不同,返回的执行器保证不会被重新配置以使用其他线程

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

可以看到发生了重载,第二个方法里加入了参数ThreadFactory

关键的是被FinalizableDelegatedExecutorService修饰了,可以确保它一旦被创建,始终保持单线程。