1 引入线程池的原因
由于线程的生命周期中包括创建、就绪、运行、阻塞、销毁阶段,当我们待处理的任务数目较小时,我们可以自己创建几个线程来处理相应的任务,但当有大量的任务时,由于创建、销毁线程需要很大的开销,运用线程池这些问题就大大的缓解了。
2 线程池的使用
我们只需要运用Executors类给我们提供的静态方法,就可以创建相应的线程池:
1
2
3
4
5
|
public static ExecutorSevice newSingleThreadExecutor()
public static ExecutorSevice newFixedThreadPool()
public static ExecutorSevice newCachedThreadPool()
|
newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。
newFixedThreadPool返回一个包含指定数目线程的线程池,如果任务数量多于线程数目,那么没有没有执行的任务必须等待,直到有任务完成为止。
newCachedThreadPool根据用户的任务数创建相应的线程来处理,该线程池不会对线程数目加以限制,完全依赖于JVM能创建线程的数量,可能引起内存不足。
我们只需要将待执行的任务放入run方法中即可,将Runnable接口的实现类交给线程池的execute方法,作为它的一个参数,如下所示:
1
2
3
4
5
6
|
Executor executor = Executors.newSingleThreadExecutor();
executor.execute( new Runnable(){
public void run(){
//执行的任务
}
}
|
如果需要给任务传递参数,可以通过创建一个Runnable接口的实现类来完成。
3.实例
(1):newSingleThreadExecutor
MyThread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
}
}
|
输出结果
1
2
3
4
5
|
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
|
(2):newFixedThreadPool
TestFixedThreadPool.Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
publicclass TestFixedThreadPool {
publicstaticvoid main(String[] args) {
//创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool( 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.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
}
}
|
输出结果
1
2
3
4
5
|
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
|
(3): newCachedThreadPool
TestCachedThreadPool.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
publicclass TestCachedThreadPool {
publicstaticvoid main(String[] args) {
//创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newCachedThreadPool();
//创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
//将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
//关闭线程池
pool.shutdown();
}
}
|
输出结果:
1
2
3
4
5
|
pool-1-thread-2正在执行。。。
pool-1-thread-4正在执行。。。
pool-1-thread-3正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-5正在执行。。。
|
(4):newScheduledThreadPool
TestScheduledThreadPoolExecutor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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);
}
}
|
输出结果
1
2
3
4
5
6
7
8
|
================
8384644549516
8386643829034
8388643830710
================
8390643851383
8392643879319
8400643939383
|