1.线程池的定义
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源,提高了代码执行效率。。
2.线程池的使用
在JDK的java.util.concurrent.Executors中提供了多种生成多种线程池的静态方法
- ExecutorService newCachedThreadPool=Executors.newCachedThreadPool();
- ExecutorService newFixedThreadPool= Executors.newFixedThreadPool(int nThreads);
- ScheduledExecutorService newScheduledThreadPool=Executors.newScheduledThreadPool(int corePoolSize);
- ExecutorService newSingleThreadExecutor=Executors.newSingleThreadExecutor();
然后调用他们的execute方法即可
3.常用的线程池有哪些
- newCachedThreadPool:创建一个可缓存的线程池,该线程池不会对线程池大小做限制,它的大小取决于操作系统(或JVM)能够创建的最大线程的大小。
- newFixedThreadPool:创建一个大小固定的线程池,每提交一个任务,就创建一个线程,直到达到线程池的最大线程大小。
- newScheduledThreadPool:创建一个支持定时和周期性执行任务的线程池。
- newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
4.使用线程池的好处
- 降低资源消耗。通过重复利用已创建的线程,从而降低创建和销毁的消耗。
- 提高响应速度。当任务到达时,不需要等待线程创建,直接可以执行任务。
- 提高线程的可管理性。使用线程池可以实现对线程统一分配、调优和监控。
5.线程池的启动策略
当调用execute()去添加一个任务时,线程会做以下判断
- 如果正在运行的线程数小于corePoolSize(核心线程数),那么马上会创建线程执行这个任务
- 如果正在运行的线程数大于或等于corePoolSize,那么会将这个这个任务放入队列。
- 如果此时队列满了,而且正在运行的线程数小于maximumPoolSize,那么还是要创建线程执行这个任务
- 如果此时队列满了,而且正在运行的线程数大于或等于maximumPoolSize,那么线程池会抛出异常,告诉调用者无法再接受任务了。
注意:(1)在这个过程中,当一个线程完成任务,它会从队列里取出下一个任务来执行
(2)当一个线程无事可做,超过一定的时间(KeepAliveTime:线程被回收前的空闲时间)时,线程池会判断;如果当前运行的线程数大于corePoolSize,那么这个线程就会被停掉。
(3)当线程池所有任务完成后,他最终会收缩到corePoolSize的大小。
下面对几个线程池进行逐一进行代码示例:
处理线程代码
class MyThread implements Runnable{
private Integer index;
public MyThread(Integer index)
{
this.index=index;
}
@Override
public void run() {
System.out.println("正在执行的线程是:"+Thread.currentThread().getName());
}
}
(1) newCachedThreadPool
创建一个可缓存线程池,应用中存在的线程数可以无限大
public class Threadpools {
public static void main(String[]args)
{
// 创建一个可缓存线程池
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for(int index=0;index<4;index++)
{
newCachedThreadPool.execute(new MyThread(index));
}
//关闭线程池
newCachedThreadPool.shutdown();
}
}
运行结果:
(2) newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
public class Threadpools {
public static void main(String[]args)
{
// 创建一个固定大小的线程池
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
for(int index=0;index<4;index++)
{
newFixedThreadPool.execute(new MyThread(index));
}
//关闭线程池
newFixedThreadPool.shutdown();
}
}
运行结果:
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下
public class Threadpools {
public static void main(String[]args)
{
// 创建一个固定大小的线程池,支持周期性及定时任务执行。
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);
for(int index=0;index<4;index++)
{
newScheduledThreadPool.schedule(new MyThread(index), 3,TimeUnit.SECONDS);
}
//关闭线程池
newScheduledThreadPool.shutdown();
}
}
运行结果:
延迟3秒后出现,除此之外其他执行结果与newFixedThreadPool相同
(4)newSingleThreadPool
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。
public class Threadpools {
public static void main(String[]args)
{
// 创建一个单线程的线程池
ExecutorService newSingleThreadPool= Executors.newSingleThreadExecutor();
for(int index=0;index<4;index++)
{
newSingleThreadPool.execute(new MyThread(index));
}
//关闭线程池
newSingleThreadPool.shutdown();
}
}