为什么要使用线程池?
例如有非常的多的任务需要多线程来完成,且每个线程执行时间不会太长,这样会频繁的创建和销毁线程。频繁创建和销毁线程会比较耗性能。如果有了线程池就不要创建更多的线程来完成任务,因为线程可以重用。
线程池用维护者一个队列,队列中保存着处于等待(空闲)状态的线程。不用每次都创建新的线程。
和线程池相关的接口和类存在java.util.concurrent并发包中。
接口:
1 Executor:线程池的核心接口,负责线程的创建使用和调度的根接口
2 ExecutorService: Executor的子接口,线程池的主要接口, 提供基本功能。
3 ScheduledExecutorService: ExecutorService的子接口,负责线程调度的子接口。
实现类:
1 ThreadPoolExecutor:ExecutorService的实现类,负责线程池的创建使用。
2 ScheduledThreadPoolExecutor:继承 ThreadPoolExecutor,并实现 ScheduledExecutorService接口,既有线程池的功能,又具有线程调度功能。
3 Executors:线程池的工具类,负责线程池的创建。
newFixedThreadPool();创建固定大小的线程池。
案例1:使用线程池完成简单的卖票
public class Ticket implements Runnable {
private int ticket = 100;
@Override
public void run() {
/* while(true){
if(ticket<1){
break;
}else{
System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"张票");
}
ticket--;
}*/
while (true){
if(!setLock()){
break;
}
}
}
public synchronized boolean setLock(){
if(ticket<1){
return false;
}else{
System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"张票");
}
ticket--;
return true;
}
}
public class ExecutorsDemo {
public static void main(String[] args) {
//创建对象
Ticket ticket = new Ticket();
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(4);//固定大小的线程池
//分配任务
for (int i = 0; i < 4; i++) {
executorService.submit(ticket);
}
//关闭
executorService.shutdown();
}
}
newCachedThreadPool();创建缓存线程池,线程池大小没有限制。根据需求自动调整线程数量。
案例二:线程池计算1-100的和,这里采用Callable接口
public class ExcutorsAndCallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();//创建缓存线程池,大小会根据需求自动调整
List<Future<Integer>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {//产生十个线程
Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int j = 0; j <= 100; j++) {
Thread.sleep(100);
sum+=j;
}
System.out.println(Thread.currentThread().getName()+"计算完毕");
return sum;
}
});
list.add(future);
}
executorService.shutdown();
System.out.println("主线程结束");
for (Future<Integer> future : list) {
int s = future.get();
System.out.println(s);
}
}
}
newSingleThreadExecutor();创建单个线程的线程池,只有一个线程。
案例三:单线程完成计算1-100的和
public class Demo3 {
public static void main(String[] args) throws Exception{
//ExecutorService executorService = Executors.newCachedThreadPool();
// ExecutorService executorService = Executors.newFixedThreadPool(5);
ExecutorService executorService = Executors.newSingleThreadExecutor();
List<Future<Integer>> list=new ArrayList<>();
//给线程池分配任务
for(int i=0;i<100;i++){
Future<Integer> future=executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
int sum=0;
for(int i=0;i<=100;i++){
sum+=i;
}
System.out.println(Thread.currentThread().getName());
return sum;
}
});
list.add(future);
}
//获取结果
for (Future<Integer> future : list) {
System.out.println(future.get());
}
executorService.shutdown();
}
}
newScheduledThreadPool();创建固定大小的线程池,可以延迟或定时执行任务。
public class Demo4 {
public static void main(String[] args) {
//1创建线程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
//2分配任务
for(int i=0;i<5;i++){
int temp=i;
// scheduledExecutorService.submit(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName()+"====="+temp);
// };
// });
// scheduledExecutorService.schedule(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName()+"..."+temp);
// }
// }, 5, TimeUnit.SECONDS);
// scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
// @Override
// public void run() {
// System.out.println(Thread.currentThread().getName()+"..."+temp);
// }
// }, 5, 1, TimeUnit.SECONDS);
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"..."+temp);
}
}, 5, 1, TimeUnit.SECONDS);
}
//3关闭
//scheduledExecutorService.shutdown();
}
}