线程池分享

醉酒当歌 提交于 2020-01-13 06:45:51

1.线程池简介
什么是线程池:
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。 
线程池作用:
一个是限制线程的数量,不会导致线程的膨胀,防止消耗过多内存;
二是线程复用,线程执行完一个人任务之后,可以接着执行下一个任务,减少了创建线程的开销;
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程和销毁线程就会大大降低系统的效率。

2.JAVA线程池详解


一、简介:
线程池中最核心的类便是ThreadPoolExecutor,而AbstractExecutorService、ExecutorService和Executor是对应的父类和接口。通过Executors工具类可以创建一些常用的线程池。

二、线程池状态
RUNNING、SHUTDOWN、STOP、TERMINATED4个状态。
当创建线程池后,初始时,线程池处于RUNNING状态;
如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;
当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。

三、java线程池构造方法
首先看一下ThreadPoolExecutor类的构造方法,在ThreadPoolExecutor类中提供了四个构造方法
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
            BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
现前面三个构造器都是调用的第四个构造器进行的初始化工作。
1)第一个使用默认线程工厂Executors.defaultThreadFactory(),使用默认的拒绝策略AbortPolicy.
2)第二个使用默认的拒绝策略AbortPolicy.
3)第三个使用默认线程工厂Executors.defaultThreadFactory().


四、线程池核心参数
下面解释下一下构造器中各个参数的含义:
corePoolSize : 核心线程数
maximumPoolSize : 线程池最大线程数
keepAliveTime : 表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用
unit : 线程池维护线程所允许的空闲时间的单位 
workQueue : 线程池所使用的阻塞队列
threadFactory:线程工厂,主要用来创建线程
handler : 线程池对拒绝任务的处理策略 

threadFactory:
默认的线程工厂会创建一个带有“ pool-poolNumber-thread-threadNumber ”为名字的线程,如果我们有特别的需要,如线程组命名、优先级等,可以定制自己的 ThreadFactory 。
Spring提供的线程池ThreadPoolTaskExecutor中,使用的是ThreadPoolTaskExecutor本身作为线程工厂,现场的名字为:beanName + "-" +threadNumber,比如:mqTaskExecutor-1274

workQueue阻塞队列有一下几种选择:
1) ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;
2) LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;
3) synchronousQueue :它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。该策略通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务
Spring提供的线程池ThreadPoolTaskExecutor中,如果队列容量queueCapacity>0,则使用LinkedBlockingQueue,否则使用的是SynchronousQueue

handler阻塞策略通常有下面4种:
1)ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
2)ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
3)ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
4)ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务


五、线程池执行过程
默认情况下,创建线程池之后,线程池中是没有线程的,需要提交任务之后才会创建线程。
一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。

当一个任务执行execute方法时: 
1)如果线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
2)如果线程池中的线程数目>=corePoolSize,则每来一个任务,会将其添加到阻塞队列中,等待其他的空闲线程去执行;
3)如果线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
4)如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过 keepAliveTime ,线程将被终止;

也就是说处理任务的优先级为: 
首先使用核心线程corePoolSize、然后使用任务队列workQueue、再使用最大线程maximumPoolSize,如果三者都满了,则使用handler拒绝策略。 

六、常用线程池
使用Executors类可以创建一些常用的线程池。
1)Executors.newCachedThreadPool()
创建一个缓冲池,缓冲池容量大小为Integer.MAX_VALUE。
如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2)Executors.newFixedThreadPool(int)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3)Executors.newSingleThreadExecutor()
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。


七、submit、Future、Callable获得线程返回结果
背景:Java多线程编程中,经常使用的Thread的Runnable()虽然被经常使用。
但其有一个弊端,就是因为无法直接获取该线程的返回值,因为Runnable内的run方法,被定义为void类型。
Java多线程中提供了Future、Callable来获取线程的返回结果。

在ThreadPoolExecutor类中提供了submit()方法来获取线程的执行结果。
public <T> Future<T> submit(Callable<T> task) {};

1)首先要定义一个“线程”实现Callable接口,在call()方法中执行线程处理逻辑并返回执行结果。
2)使用线程池中的 submit(Callable<T> task)方法提交线程,并返回Future对象。
3)调用future.get()方法获取子线程返回的结果。

3.spring线程池使用


4.线程监控工具
 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!