线程池概述
什么是线程池?
线程池就是一个可以复用线程的技术
不使用线程池的问题?
如果用户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能
谁代表线程池?
JDK5.0提供了代表线程池的接口:ExecutorService
如何得到线程池对象
方式1:使用ExecutorService的实现类ThreadPoolExecutor自动创建一个线程池对象
方式2:使用Executors(线程池工具类) 调用方法返回不同特点的线程池对象
ThreadPoolExecutor构造器
public ThreadPoolExecutor(int corePoolSize,int maxiumPoolSize,long KeepAlivetime,TimeUnit unit,BlockingQueue<Runnable > workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
参数1:线程池的线程数量(核心线程) corePoolSize 不能小于零
参数2:线程池可支持的最大线程数:maxImumPoolSize 最大数量>=核心线程数量
参数3:临时线程最大存活时间 :keepAliveTime 不能小于零
参数4:存活时间单位(秒,分,时,天) unit
参数5:指定任务队列 workQueue 不能为null
参数6:指定用哪个线程工厂创建线程 threadFactory 不能为null
参数7:线程忙任务满时,新任务来了怎么办 handler 不能为null
临时线程什么时候创建?
新任务提交时候发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程
什么时候会开始拒绝任务?
核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始任务拒绝
新任务拒绝策略
ThreadPoolExecutor.AbortPolicy 丢弃任务并抛出RejectededExecutionException 异常,是默认的策略
ThreadPoolExecutor.DiscardPolicy 丢弃任务,但是不抛出异常,这是不推荐的做法
ThreadPoolExecutor.DiscardOldestPolicy 抛弃队列中等待最久的任务,然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunsPolicy 由主线程负责调用任务的run()方法从而绕过线程池直接执行
线程池如何处理Runnable任务
使用ExecutorService 的方法
void execute(Runnable target) 执行任务、命令,没有返回值,一班用来执行Runnable任务
线程类(加了休眠方法方便测试)
package 线程池;
public class Mypool implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<5;i++) {
System.out.println(Thread.currentThread().getName()+"正在输出"+i);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
主函数
package 线程池;
import java.lang.reflect.Executable;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
ExecutorService pool=new ThreadPoolExecutor(3, 5, 10, TimeUnit.MINUTES,new ArrayBlockingQueue<>(2),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
Runnable r=new Mypool();
pool.execute(r);
pool.execute(r);
pool.execute(r);
//我在线程中加了休眠,主线程不够用开始创建临时线程,临时线程最多创建两个
pool.execute(r);
pool.execute(r);
//临时线程满了,开始向等待队列中加数据,等待队列容器为2
pool.execute(r);
pool.execute(r);
//pool.execute(r); 队列满了抛异常
//不常用了解
//pool.shutdown();//等待执行完毕后关闭线程池
//pool.shutdownNow();//线程池在干着活也会直接强制关闭
}
}
线程池处理Callable任务
Future<T> submit(Callable<T> tast ) 执行Callable任务,返回未来任务对象获取线程结果
线程类
package 线程池;
import java.util.concurrent.Callable;
public class ReMythread implements Callable<Integer>{
private int a;
private int b;
public ReMythread(int a,int b) {
this.a=a;
this.b=b;
}
//随便简单写个功能测试一下
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"正在执行");
int sum=a+b;
return sum;
}
}
主函数
package 线程池;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.lang.model.element.ModuleElement.ExportsDirective;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService pool=new ThreadPoolExecutor(3, 5,1000, TimeUnit.MINUTES,new ArrayBlockingQueue<>(3));
//使用未来任务对象接收返回值
Future<Integer> f1=pool.submit(new ReMythread(10, 20));
Future<Integer> f2=pool.submit(new ReMythread(100,100));
try {
Integer s=f1.get();//取返回值
System.out.println("f1:"+s);
System.out.println("f2:"+f2.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}