线程6-线程池

1、几个概念:
(1)线程池 ThreadPoolExecutor:存放线程的池子( --!)
(2)线程 Thread:用于执行实现<Runnable>接口的任务
(3)任务缓存队列:用于存放Thread要执行的任务
2、几个变量和方法的解释
(1)ThreadPoolExecutor的构造方法参数
corePoolSize:核心池的大小,在创建了线程池后,默认情况下,线程数为0。当有任务来了之后,就创建一个线程
去执行任务,当线程池中的线程数达到corePoolSize之后,就会尝试把新到达的任务放到缓存队列中
maximumPoolSize:线程池中最大线程数
keepAliveTime:线程池中的某个线程在多久没有执行任务时,线程会终止
unit:参数keepAliveTime的时间单位,有7种取值,参见TimeUnit类
workQueue:一个阻塞队列,用来存储等待执行的**任务**(非线程),阻塞队列有以下几种选择
一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
(2)execute()方法,可向线程池提交一个任务,交由线程池去执行
(3)submit()方法,也是向线程池提交一个任务,它能够返回任务结果,看源码可知,
其实submit()也是调用了execute,只不过它使用了RunnableFutureo类来获取线程执行结果
(4)shutdown(),等所有任务执行完毕后,关闭线程池
(5)shutdownNow(),马上关闭线程池,不管任务是否完成
(6)拒绝策略,通常有以下4种策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
(7)任务缓存队列及排队策略
任务缓存策略,即workQueue,用来等待任务执行的任务
workQueue通常有以下3种类型
1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE(0x7fffffff);
3)synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
(8)在ThreadPoolExecutor类中定义了一个volate变量,用来指示线程池状态,线程池有4种状态
1)static final int RUNNING = 0;
2)static final int SHUTDOWN = 1;
3)static final int STOP = 2;
4)static final int TERMINATED = 3;
创建后,线程池处于RUNNING状态
shutdown()后,线程处于SHUTDOWN状态,此时它只等待所有线程执行完任务,不接受新任务
shotdownNow()后,线程处于STOP状态,它不接受任务,尝试终止正在执行的任务
线程池处于STOP状态后,并且所有工作线程已销毁,任务缓存队列已清空或执行结束后,线程池被置为TERMINATED(结束)状态
3、线程池的工作流程
创建线程池(ThreadPoolExecutor)时,会指定核心池(corePoolSize)和线程池的最大线程容量(maximumPoolSize)
(1)创建线程池,线程池中线程为0,任务缓存队列中的任务为0
(2)ThreadPoolExecutor对象使用execute方法,向线程池提交一个任务
(3)线程池拿到任务,进行判断
如果当前线程池中的线程数,=<corePoolSize,创建一个新线程去执行任务
如果当前线程池中的线程数,大于corePoolSize并且小于maximumPoolSize,
则线程池会尝试把任务放到任务缓存队列,
如果放入缓存队列失败(一般来说是任务缓存队列已满),线程池尝试创建线程来执行任务
放入缓存队列成功,任务就等待空闲线程来取出执行
如果当前线程池中的线程数,等于maximunPoolSize,
则线程池会尝试把任务放到任务缓存队列,
如果放入缓存队列成功,任务就等待空闲线程来取出执行
如果放入缓存队列失败(一般来说是任务缓存队列已满),则会采取拒绝策略进行处理
4、线程池例子

package com.线程池;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test {
    public void testThread() throws InterruptedException {
         
        /**线程池构造方法中
         *  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue)
               (1)corePoolSize:核心池的大小,在创建了线程池后,默认情况下,线程数为0当有任务来了之后,就创建一个线程
               去执行任务,当线程池中的线程数达到corePoolSize之后,就会把新到达的任务放到缓存队列中
               (2)maximumPoolSize:线程中最大线程数
               (3)keepAliveTime:线程池中的某个线程在多久没有执行任务时,会终止
               (4)unit:参数keepAliveTime的时间单位,有7种取值,参见TimeUnit类
               (5)workQueue:一个阻塞队列,用来存储等待执行的**任务**(非线程),阻塞队列有以下几种选择:
               ArrayBlockingQueue;
            LinkedBlockingQueue;
            SynchronousQueue;
            ArrayBlockingQueue和PriorityBlockingQueue使用较少,
            一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(6));//参数6是阻塞队列的容量
        
        //执行任务
        for(int i = 0 ; i < 15 ; i ++){
            MyMask mask = new MyMask(i);
            /**
             * ThreadPoolExecutor的四个方法
             * (1)execute()方法,可向线程池提交一个任务,交由线程池去执行
             * (2)submit()方法,也是向线程池提交一个任务,它能够返回任务结果,看源码可知,
             *     其实submit()也是调用了execute,只不过它使用了RunnableFutureo类来获取线程执行结果
             * (3)shutdown(),等所有任务执行完毕后,关闭线程池
             * (4)shutdownNow(),马上关闭线程池,不管任务是否完成
             */
             
            executor.execute(mask);
            System.out.println("线程池中的线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数:"+executor.getQueue().size()
                    +",已执行完的任务数:"+executor.getCompletedTaskCount());
            //Thread.currentThread();
            //Thread.sleep(2000);
        }
        executor.shutdown();
        
    }
    public static void main(String[] args) {
        Test test = new Test();
        try {
            test.testThread();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class MyMask implements Runnable{
    private Integer intNum;
    
    public MyMask(int num){
        this.intNum = num;
    }

    @Override
    public void run() {
        System.out.println("正在执行task "+intNum);
        
        Thread.currentThread();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("task "+intNum+"执行完成");
        
    }
    
}

参考:http://www.cnblogs.com/dolphin0520/p/3932921.html 原文写的很棒,讲的非常清晰,这篇博客是我按照自己的理解方式,重新整理了一下。

原文地址:https://www.cnblogs.com/fubaizhaizhuren/p/5067134.html