java⾃带线程池和队列详细讲解
Java线程池使⽤说明
⼀简介
线程的使⽤在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使⽤是极其简陋的。在jdk1.5之后这⼀情况有了很⼤的改观。Jdk1.5之后加⼊了urrent包,这个包中主要介绍java中线程以及线程池的使⽤。为我们在开发中处理线程的问题提供了⾮常⼤的帮助。
⼆:线程池
线程池的作⽤:
线程池作⽤就是限制系统中执⾏线程的数量。
根据系统的环境情况,可以⾃动或⼿动设置线程数量,达到运⾏的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不⾼。⽤线程池控制线程数量,其他线程排队等候。⼀个任务执⾏完毕,再从队列的中取最前⾯的任务开始执⾏。若队列中没有等待进程,线程池的这⼀资源处于等待。当⼀个新任务需要运⾏时,如果线程池中有等待的⼯作线程,就可以开始运⾏了;否则进⼊等待队列。
为什么要⽤线程池:
1.减少了创建和销毁线程的次数,每个⼯作线程都可以被重复利⽤,可执⾏多个任务。
2.可以根据系统的承受能⼒,调整线程池中⼯作线线程的数⽬,防⽌因为消耗过多的内存,⽽把服务器累趴下(每个线程需要⼤约1MB内存,线程开的越多,消耗的内存也就越⼤,最后死机)。
Java⾥⾯线程池的顶级接⼝是Executor,但是严格意义上讲Executor并不是⼀个线程池,⽽只是⼀个执⾏线程的⼯具。真正的线程池接⼝是ExecutorService。
⽐较重要的⼏个类:
ExecutorService真正的线程池接⼝。
ScheduledExecutorService能和Timer/TimerTask类似,解决那些需要任务重复执⾏
的问题。
ThreadPoolExecutor ExecutorService的默认实现。
ScheduledThreadPoolExecutor继承ThreadPoolExecutor的ScheduledExecutorService
接⼝实现,周期性任务调度的类实现。
要配置⼀个线程池是⽐较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在Executors类⾥⾯提供了⼀些静态⼯⼚,⽣成⼀些常⽤的线程池。
1. newSingleThreadExecutor
创建⼀个单线程的线程池。这个线程池只有⼀个线程在⼯作,也就是相当于单线程串⾏执⾏所有任务。如果这个唯⼀的线程因为异常结束,那么会有⼀个新的线程来替代它。此线程池保证所有任务的执⾏顺序按照任务的提交顺序执⾏。
创建固定⼤⼩的线程池。每次提交⼀个任务就创建⼀个线程,直到线程达到线程池的最⼤⼤⼩。线程池的⼤⼩⼀旦达到最⼤值就会保持不变,如果某个线程因为执⾏异常⽽结束,那么线程池会补充⼀个新线程。
3. newCachedThreadPool
创建⼀个可缓存的线程池。如果线程池的⼤⼩超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执⾏任务)的线程,当任务数增加时,此线程池⼜可以智能的添加新线程来处理任务。此线程池不会对线程池⼤⼩做限制,线程池⼤⼩完全依赖于操作系统(或者说JVM)能够创建的最⼤线程⼤⼩。
创建⼀个⼤⼩⽆限的线程池。此线程池⽀持定时以及周期性执⾏任务的需求。
实例
1:newSingleThreadExecutor
MyThread.java
publicclassMyThread extends Thread {
@Override
publicvoid run() {
System.out.println(Thread.currentThread().getName() + "正在执⾏。。。");
}
}
TestSingleThreadExecutor.java
publicclassTestSingleThreadExecutor {
publicstaticvoid main(String[] args) {
//创建⼀个可重⽤固定线程数的线程池
ExecutorService pool = Executors. newSingleThreadExecutor();
//创建实现了Runnable接⼝对象,Thread对象当然也实现了Runnable接⼝
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放⼊池中进⾏执⾏
//关闭线程池
pool.shutdown();
}
}
输出结果
pool-1-thread-1正在执⾏。。。
pool-1-thread-1正在执⾏。。。
pool-1-thread-1正在执⾏。。。
pool-1-thread-1正在执⾏。。。
pool-1-thread-1正在执⾏。。。
2newFixedThreadPool
TestFixedThreadPool.Java
publicclass TestFixedThreadPool {
publicstaticvoid main(String[] args) {
/
/创建⼀个可重⽤固定线程数的线程池
ExecutorService pool = wFixedThreadPool(2);
//创建实现了Runnable接⼝对象,Thread对象当然也实现了Runnable接⼝ Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放⼊池中进⾏执⾏
//关闭线程池
pool.shutdown();
}
}
输出结果
pool-1-thread-1正在执⾏。。。
pool-1-thread-2正在执⾏。。。
pool-1-thread-1正在执⾏。。。
pool-1-thread-2正在执⾏。。。
pool-1-thread-1正在执⾏。。。
3 newCachedThreadPool
TestCachedThreadPool.java
publicclass TestCachedThreadPool {
publicstaticvoid main(String[] args) {
//创建⼀个可重⽤固定线程数的线程池
ExecutorService pool = wCachedThreadPool();
//创建实现了Runnable接⼝对象,Thread对象当然也实现了Runnable接⼝ Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放⼊池中进⾏执⾏
//关闭线程池
pool.shutdown();
}
}
输出结果:
pool-1-thread-2正在执⾏。。。
pool-1-thread-4正在执⾏。。。
pool-1-thread-3正在执⾏。。。
pool-1-thread-1正在执⾏。。。
4newScheduledThreadPool
TestScheduledThreadPoolExecutor.java
publicclass TestScheduledThreadPoolExecutor {
publicstaticvoid main(String[] args) {
ScheduledThreadPoolExecutor exec = new
ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {//每隔⼀段时间就触发异常
@Override
publicvoid run() {
//throw new RuntimeException();
System.out.println("================");
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
exec.scheduleAtFixedRate(new Runnable() {//每隔⼀段时间打印系统时间,
证明两者是互不影响的
@Override
publicvoid run() {
System.out.println(System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
}
}
输出结果
================
8384644549516
8386643829034
8388643830710
================
8390643851383
8392643879319
8400643939383
三:ThreadPoolExecutor详解
ThreadPoolExecutor的完整构造⽅法的签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) .
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize-池中允许的最⼤线程数。