概述
之前我们有学习过java的线程,但我们知道,进程才是系统分配资源的最小单位。实际使用过程中,比如我们打开了浏览器,它会对应启动多个进程。而每个进程中又包含着多个线程。那也就是说,实际工作使用时,很少会使用单个的线程来完成某项任务。那对于很多线程使用的情况,我们应该怎么合理的节省系统资源呢?
于是在这里引入了线程池的概念。那什么是线程池呢?通俗来讲,就是一个存放线程的容器。java5之后,java引入了自带的线程池管理框架Executor,今天我们简单介绍下这个框架的使用。
为什么使用线程池
假设每条线程的创建时间为t1,线程工作时间为t2,线程销毁时间为t3.那如果处理器每天处理的线程数是50000,那不使用线程池的时候,需要花费的时间为50000(t1+t2+t3),而假设我们使用了一个合适容量的线程池,那么我们就省去了t1和t3的时间,提高了处理器的利用率(这说法不完全准确,需要结合处理器性能,系统设计等实际情况去比对)。可以这样说:如果:t1 + t3 远大于 t2,则可以采用线程池,以提高服务器性能。
常用的线程池类型及简单实现
- singleThreadExecutor
可以创建只含有一条线程的线程池。如果需要多条线程完成任务,则任务需要依次执行。请参见代码:
/**
* newSingleThreadExecutor创建只有一条线程的线程池
* 所以在执行线程时,虽然用线程池加载了三个线程对象,但由于线程池只有一条线程,所以输出结果是三个线程依次执行
*/
public void singleThread(){
//通过Executors工具类 的newSingleThreadExecutor方法创建线程池
ExecutorService e=Executors.newSingleThreadExecutor();
//创建线程对象
Thread t1=new Thread(new RunnableDemo("why"));
Thread t2=new Thread(new RunnableDemo("sb"));
Thread t3=new Thread(new RunnableDemo("zzh"));
//使用线程池调度线程
e.execute(t1);
e.execute(t2);
e.execute(t3);
//关闭线程池
e.shutdown();
}
- FixedThreadPool
创建含有固定条数线程的线程池。具体使用参见下例:
/**
* newFixedThreadPool(int num)
该方法会按照用户指定的数据创建固定线程数的线程池。如下例为3
* 所以在使用的时候,若需要的线程数不大于3时,线程池会自动分配线程,执行操作。若超出3(线程池最大线程数),则需要前面占用线程释放后,才会执行后面的线程计划
*/
public void fixedThread(){
//通过Executors工具类 的newFixedThreadPool方法创建线程池
ExecutorService e =Executors.newFixedThreadPool(3); //指定线程池线程数为3
//创建线程对象
Thread t1=new Thread(new RunnableDemo("why"));
Thread t2=new Thread(new RunnableDemo("sb"));
Thread t3=new Thread(new RunnableDemo("zzh"));
Thread t4=new Thread(new RunnableDemo("aiguo"));
//使用线程池调度线程
e.execute(t1);
e.execute(t2);
e.execute(t3);
e.execute(t4);
//关闭线程池
e.shutdown();
}
- CachedThreadPool
创建一个可缓存的线程池。线程池中的线程数可以按照实际需求自行调整。
/**
* newCachedThreadPool()可以创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
* 那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
* 此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
*/
public void cacheThread(){
//通过Executors工具类 的newCachedThreadPool方法创建线程池
ExecutorService e =Executors.newCachedThreadPool();
//创建线程对象
Thread t1=new Thread(new RunnableDemo("why"));
Thread t2=new Thread(new RunnableDemo("sb"));
Thread t3=new Thread(new RunnableDemo("zzh"));
Thread t4=new Thread(new RunnableDemo("aiguo"));
//使用线程池调度线程
e.execute(t1);
e.execute(t2);
e.execute(t3);
e.execute(t4);
//关闭线程池
e.shutdown();
}
- ScheduledThreadPool
创建一个定时执行的线程池。一般来说推荐使用上面三种,这种很少使用。
/**
* 使用ScheduledThreadPoolExecutor来构造线程池 (很少使用)
*
1.固定频率来执行指定操作
*/
public void scheduleThread(){
ScheduledThreadPoolExecutor e=new ScheduledThreadPoolExecutor(1);
//指定线程池中的线程数。若线程数小于需要线程数,则需要等待前面线程执行完成后再执行
e.scheduleAtFixedRate(new RunnableDemo("why"), 1000, 1000, TimeUnit.MILLISECONDS);//构造参数为:(进程,初始时间,间隔时间,时间单位)
e.scheduleAtFixedRate(new RunnableDemo("sb"), 1000, 5000, TimeUnit.MILLISECONDS);
}
ThreadPoolExecutor详解(扩展内容,有兴趣的可以去查阅源码)
ThreadPoolExecutor的完整构造方法的签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) .
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize-池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute方法提交的 Runnable任务。
threadFactory - 执行程序创建新线程时使用的工厂。
handler - 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序。
ThreadPoolExecutor是Executors类的底层实现。
在JDK帮助文档中,有如此一段话:
“强烈建议程序员使用较为方便的Executors工厂方法Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、Executors.newFixedThreadPool(int)(固定大小线程池)Executors.newSingleThreadExecutor()(单个后台线程),它们均为大多数使用场景预定义了设置。”
最后
以上就是贪玩钢笔为你收集整理的java自带线程池的简单使用的全部内容,希望文章能够帮你解决java自带线程池的简单使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复