线程池简介
创建若干个线程,放入池中,有任务需要处理了就提交到任务队列中,处理完不会销毁线程,而是仍然在任务队列中等待下个任务。
线程池优点
-
重复利用
-
提高响应速度(没有cpu时间调度)
-
管理线程
线程池的体系结构
java.util.concurrent.Executor : 负责线程的使用与调度的根接口
|--ExecutorService 子接口: 线程池的主要接口
|--ThreadPoolExecutor 线程池的实现类
|--ScheduledExecutorService 子接口:负责线程的调度
|--ScheduledThreadPoolExecutor :继承 ThreadPoolExecutor, 实现 ScheduledExecutor
Executor封装好了四种连接池类型
- newCachedThreadPool:缓存线程池,线程池的数量不固定,可以根据需求自动的更改数量。
- newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。(工作中用的比较多)
- newScheduledThreadPool:创建固定大小的线程,可以延迟或定时的执行任务。
- newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
传统线程
for (int i = 0; i < 20; i++) {
final int tmp = i;
new Thread(new Runnable() {
public void run() {
System.out.println("传统创建线程"+Thread.currentThread().getName()+","+tmp);
}
}).start();
}
newCachedThreadPool
可缓存的线程 重复利用线程
//1.可缓存的线程 重复利用线程
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
final int tmp = i;
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp);
}
});
}
打印如下:
threadName:pool-1-thread-2,1
threadName:pool-1-thread-4,3
threadName:pool-1-thread-5,4
threadName:pool-1-thread-6,5
threadName:pool-1-thread-3,2
threadName:pool-1-thread-8,7
threadName:pool-1-thread-1,0
threadName:pool-1-thread-9,8
threadName:pool-1-thread-7,6
threadName:pool-1-thread-6,11
threadName:pool-1-thread-4,16
threadName:pool-1-thread-5,17
threadName:pool-1-thread-1,13
threadName:pool-1-thread-3,15
threadName:pool-1-thread-7,19
threadName:pool-1-thread-11,10
threadName:pool-1-thread-10,9
threadName:pool-1-thread-2,18
threadName:pool-1-thread-9,12
threadName:pool-1-thread-8,14
上图线程池只创建11个线程,相比传统线程,会创建20个线程,节省开销。
newFixedThreadPool
固定长度线程池
//2.固定长度线程池
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int tmp = i;
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp);
}
});
}
打印如下:
threadName:pool-1-thread-3,2
threadName:pool-1-thread-5,4
threadName:pool-1-thread-4,3
threadName:pool-1-thread-2,1
threadName:pool-1-thread-1,0
threadName:pool-1-thread-2,8
threadName:pool-1-thread-4,7
threadName:pool-1-thread-3,5
threadName:pool-1-thread-5,6
threadName:pool-1-thread-1,9
newScheduledThreadPool
固定长度任务调度线程池
//3.固定长度任务调度线程池
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
final int tmp = i;
newScheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp);
}
},3,TimeUnit.SECONDS);//3秒后同时执行
}
newSingleThreadExecutor
单线程
//4. 单线程
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int tmp = i;
newSingleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp);
}
});
}
终止线程池
所有线程池在运行完后,后台都会在执行,需要调用shutdown方法,该方法调用后需要等待线程池中的线程执行完毕后再关闭进程。
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int tmp = i;
newSingleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+","+tmp);
}
});
}
//终止线程池
newSingleThreadExecutor.shutdown();
线程池和Callable的使用方式
线程池submit方法,在之前中一直使用execute方法,exeute存放Runnable类型的接口,submit方法存放Callable接口的线程,并且可以抛出异常和返回值。
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
Future<Integer> future = newCachedThreadPool.submit(new Callable<Integer>() {
public Integer call(){
int sum = 0;
for (int i = 0;i<100;i++) {
sum += i;
}
return sum;
}
});
newCachedThreadPool.shutdown();
System.out.println(future.get());