线程池的简介:线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。
为什么要使用线程池
在java中,如果每个请求到达就创建一个新线程,开销是相当大的。在实际使用中,服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个jvm里创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要采取一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务,这就是“池化资源”技术产生的原因。
线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。
要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。
1.newSingleThreadExecutor
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的
的线程因为异常结束,那么会有一个新的线程来替代他,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2. newFixedThreadPool
创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就保持不变,如果某个线程因为执行异常而结束,那么线程池就会补充一个新线程。
3. newCachedThreadPool
创建一个可缓存的线程池,如果线程池的大小超过了处理任务所需要的线程,那么可回收部分空闲的线程(60秒不执行的任务),当任务数增加的时候,此线程有可以智能 的添加新线程来处理任务,次线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说jvm)能创建的最大线程大小。
4. newScheduledThreadPool
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
部分代码
public class cachpool {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//单线程线程池
//ExecutorService es=Executors.newSingleThreadExecutor();
//可缓存的线程池
//ExecutorService es=Executors.newCachedThreadPool();
//固定大小的线程池
ExecutorService es=Executors.newFixedThreadPool(2);
//创建一个无限制的线程池
//ExecutorService es=Executors.newScheduledThreadPool(2);
// t1 t=new t1();
// t2 t1=new t2();
// es.execute(t1);
thread t=new thread();
thread t1=new thread();
thread t2=new thread();
es.execute(t);
es.execute(t1);
es.execute(t2);
}
}
class thread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("faf"+i);
}
}
}