线程池

1.1为什么要有线程池?
当有一个请求到达的时候,就要创建一个线程,开销相当大,在实际情况中,每个请求创建新线程的服务器在创建和销毁线程上花费的时间
和消耗的资源,有时会比花费在处理实际用户的请求上的时间和资源还要多。除了创建和销毁线程之外,活动的线程也需要消耗系统资源。
创建过多的线程,可能会导致系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要一些方法来限制
任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,尽量利用现有对象来进行服务。
1.2引进线性池的好处:
(1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
(2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。减少创建和销毁线程的次数,多个任务重复使用线程,线程创建的开销被多个任务
分担,请求到达时线程已经存在,消除线程创建带来的延迟,应用程序响应加快;
(3)提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用线程池,必须对其实现原理了如指掌。可根据系统情况调整执行线程数量,防止消耗过多内存,资源不足问题。

2、线程池的类的继承关系?

Executor接口:(void execute(Runnable command))该接口定义执行Runnable任务的方式;

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

ThreadPoolExecutor类:线程池具体实现,

public class ThreadPoolExecutor extends AbstractExecutorService 

Executors类:提供工厂方法用于创建线程池,线程池工厂类,提供了一系列工厂方法用于创建线程池,

返回的线程池都实现了ExecutorService接口;

public class Executors 

ScheduledExecutorService定时调度接口

public interface ScheduledExecutorService extends ExecutorService

ExecutorService接口:增加Executor的行为,是Executor实现类的最直接的接口,该接口定义提供对Executor的服务;

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;
}

AbstractExecutorService抽象类:实现ExecutorService接口,并且提供了一些方法的默认实现,例如submit方法、invokeAny方法、invokeAll方法。像execute方法、线程池的关闭方法(shutdown、shutdownNow等等)就没有提供默认的实现。

public abstract class AbstractExecutorService implements ExecutorService {

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }

    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {...}

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {... }

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

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {...}

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

}
  • 构造函数:
 ThreadPoolExecutor(int corePoolSize, 
                     int maximumPoolSize, 
         long keepAliveTime, 
         TimeUnit unit, BlockingQueue<Runnable> workQueue) 
        用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。
        ThreadPoolExecutor(int corePoolSize, 
                     int maximumPoolSize, 
         long keepAliveTime, 
         TimeUnit unit, 
         BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) 
          用给定的初始参数和默认的线程工厂创建新的 ThreadPoolExecutor。
        ThreadPoolExecutor(int corePoolSize, 
                     int maximumPoolSize, 
         long keepAliveTime, 
         TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) 
          用给定的初始参数和默认被拒绝的执行处理程序创建新的 ThreadPoolExecutor。
        ThreadPoolExecutor(int corePoolSize, 
                     int maximumPoolSize, 
         long keepAliveTime, 
         TimeUnit unit, 
         BlockingQueue<Runnable> workQueue, 
         ThreadFactory threadFactory, RejectedExecutionHandler handler) 
          用给定的初始参数创建新的 ThreadPoolExecutor。
  • 基本方法:
private final BlockingQueue workQueue;              
//任务缓存队列,用来存放等待执行的任务
private final ReentrantLock mainLock = new ReentrantLock();   
//线程池的主要状态锁,对线程池状态(比如线程池大小、runState等)的改变都要使用这个锁
private final HashSet workers = new HashSet();  
//用来存放工作集 
private volatile long  keepAliveTime;    //线程存货时间 
//使用的场合:  
private volatile boolean allowCoreThreadTimeOut;  
 //是否允许为核心线程设置存活时间
private volatile int   corePoolSize;     
//核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)
private volatile int   maximumPoolSize;   
//线程池最大能容忍的线程数
private volatile int   poolSize;       
//线程池中当前的线程数
private volatile RejectedExecutionHandler handler; 
//任务拒绝策略 
private volatile ThreadFactory threadFactory;   
//线程工厂,用来创建线程 
private int largestPoolSize;  
//用来记录线程池中曾经出现过的最大线程数 
private long completedTaskCount;  
 //用来记录已经执行完毕的任务个数
  • 基本属性:
 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));//原子操作类ctl

    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;//线程容量

    // runState is stored in the high-order bits  线程池状态
    private static final int RUNNING    = -1 << COUNT_BITS;//正常运行状态 1110000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
	//线程池关闭状态(不接受新任务,但是处理已经进入队列的任务)
    private static final int STOP       =  1 << COUNT_BITS;
	//不接受任务,不处理已经进入队列的任务,并且Interrupt(中断)正在执行的任务
    private static final int TIDYING    =  2 << COUNT_BITS;
	//所有任务完成,workcount==0 ,线程转到此状态会执行 terminated()钩子方法;
    private static final int TERMINATED =  3 << COUNT_BITS;
	//terminated()已经执行完成

    // Packing and unpacking ctl
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
	//得到当前线程池状态
    private static int workerCountOf(int c)  { return c & CAPACITY; }
	//返回当前正在运行的线程数
    private static int ctlOf(int rs, int wc) { return rs | wc; }
	//将线程池的数量和线程状态合并
  • 线性池的创建
创建线程池:
    一个简单的线程池有线程池管理器、工作线程、任务队列、任务接口等。
    其中线程池管理器(ThreadPool Manager)的作用是创建、销毁并管理线程池,将工作线程放入线程池中;
        工作线程是一个可以循环执行任务的线程,在没有任务时进行等待;
     任务队列的作用是提供一种缓冲机制,将没有处理的任务放在任务队列中;
     任务接口是每个任务必须实现的接口,主要用来规定任务的入口、任务执行完后的收尾工作、任务的执行状态等。
     工作线程通过该接口调度任务的执行。
  • handler:表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:
//丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:
//也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:
//丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:
//由调用线程处理该任务
  • 线性池的关闭:
ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

shutdown():不会立即终止线程池,
而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,
并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
  • 线性池的大小调整:
ThreadPoolExecutor提供了动态调整线程池容量大小的方法:
 setCorePoolSize()和setMaximumPoolSize(),
setCorePoolSize:设置核心池大小
setMaximumPoolSize:设置线程池最大能创建的线程数目大小
当上述参数从小变大时,ThreadPoolExecutor进行线程赋值,
还可能立即创建新的线程来执行任务。
  • 线性池中的线程的初始化:
默认情况下,创建线程池之后,线程池中是没有线程的,
需要提交任务之后才会创建线程。
在实际中如果需要线程池创建之后立即创建线程,可以通过以下两个方法办到:
prestartCoreThread():初始化一个核心线程;
prestartAllCoreThreads():初始化所有核心线程
  下面是这2个方法的实现:
  public boolean prestartCoreThread() {
    return addIfUnderCorePoolSize(null);
     //注意传进去的参数是null
}

public int prestartAllCoreThreads() {
    int n = 0;
    while (addIfUnderCorePoolSize(null))
    //注意传进去的参数是null
        ++n;
    return n;
}
  • Executors静态工厂的几种线程池:
(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

代码示例:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        final int index = i;
    try {
        Thread.sleep(index * 1000);
    } 
        catch (InterruptedException e) {
            e.printStackTrace();
    }
    cachedThreadPool.execute(new Runnable() {

@Override
public void run() {
    System.out.println(index);
}
});
}
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

 (2)newFixedThreadPool 创建一个定长线程池(线程池中的线程个数是固定的),可控制线程最大并发数,超出的线程会在队列中等待。
 
代码示例:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 10; i++) {
    final int index = i;
 fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
    System.out.println(index);
    Thread.sleep(2000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
}
});
}  
 (3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
 
  延迟执行示例代码如下:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
 scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
    System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
表示延迟3秒执行。

 定期执行示例代码如下:

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
    System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
表示延迟1秒后每3秒执行一次。
ScheduledExecutorService比Timer更安全,功能更强大


 (4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务, 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

代码示例:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
    try {
        System.out.println(index);
    Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
        }
}
    });
}

addWorker():

private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) { //CAS操作, 将线程池数量+1
            int c = ctl.get(); 
            int rs = runStateOf(c);// 当前线程池状态
             // Check if queue empty only if necessary.
            //当前的运行状态不为Running或者在Shutdown状态下(不接受新任务但是会执行完队列中的任务)
            //如果处于shutdown状态,并且阻塞队列为空
			//仅在必要时检查队列是否为空
            if (rs >= SHUTDOWN &&  //shutdown状态或者别的非运行状态
                ! (rs == SHUTDOWN &&  //不再接受新的任务,等待线程执行完毕
                   firstTask == null && //传入任务为空
                   ! workQueue.isEmpty())) //阻塞队列为空时,后面结果为True
                return false;
            //要么处于running状态要么shutdown状态下还有线程在执行,可以添加
            for (;;) { 
                int wc = workerCountOf(c); //正在运行线程数量
                if (wc >= CAPACITY ||  //正在运行线程数量大于等于容量
                    //线程数量不能大于最大容量
                    wc >= (core ? corePoolSize : maximumPoolSize)) 
                    // true用核心线程数量比较,false用最大线程数量比较
                    return false;
 //CAS将线程数+1,在线程池为将要添加的线程留出空间
                if (compareAndIncrementWorkerCount(c)) //CAS将线程数量自增1
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs) //检查一下运行状态是否改变,
                //如果改变将从外循环开始执行,再次确认能否添加任务。
                    continue retry; 
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

//下面创建一个新的work实例
boolean workerStarted = false; //线程是否启动
        boolean workerAdded = false; //线程是否添加成功
        Worker w = null;
        try {
            final ReentrantLock mainLock = this.mainLock; //得到一个重入锁
            w = new Worker(firstTask);  //创建一个工作任务
            final Thread t = w.thread; //当前任务线程
            if (t != null) { //线程不为空
                mainLock.lock(); //加锁
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int c = ctl.get(); 
                    int rs = runStateOf(c);  //线程状态

if (rs < SHUTDOWN || //线程池处于运行状态
                        (rs == SHUTDOWN && firstTask == null)) {//线程池全部线程死掉,创建一个空线程
                        if (t.isAlive()) // precheck that t is startable
                        //线程已经启动,并且没有异常返回true。在这里已经启动的线程是不需要添加的,需要抛出异常
                            throw new IllegalThreadStateException();
                        workers.add(w); //将线程加入到线程池中
                        int s = workers.size();  //线程池线程数量
                        if (s > largestPoolSize) //修正最多运行线程值
                            largestPoolSize = s; //最多时工作线程数量
                        workerAdded = true; //线程添加成功标志
                    }
                } finally {
                    mainLock.unlock(); //解锁
                }
                if (workerAdded) { //线程添加线程池成功,启动线程
                    t.start(); 
                    workerStarted = true; //线程开启成功标志
                }
            }
        } finally {
            if (! workerStarted) //线程未启动成功,从线程池中删除线程并且回滚线程池元素个数
                addWorkerFailed(w);
        }
        return workerStarted; //线程启动成功才算添加完成
    }
 /**
     * Rolls back the worker thread creation.
     * - removes worker from workers, if present
     * - decrements worker count
     * - rechecks for termination, in case the existence of this
     *   worker was holding up termination
     */
    private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null) //线程
                workers.remove(w); //工作线程集合删除
            decrementWorkerCount(); //线程数量-1
            tryTerminate(); //尝试终止线程
        } finally {
            mainLock.unlock();
        }
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值