不使用线程池,如果客户每发起一个请求,后台就创建一个新线程来处理,下次新任务来了又要创建新线程,而创建新线程的开销是很大的,这样会严重影响系统的性能。
1、使用ExecutorService
的实现类ThreadPoolExecutor
自创建一个线程池对象。
2、使用Executors
(线程池的工具类)调用方法返回不同特点的线程池对象。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable>,workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
参数一:指定线程池的线程数量(核心线程):corePoolSize 不能小于0
参数二:指定线程池可支持的最大线程数:maximumPoolSize 最大数量>=核心线程数量
参数三:指定临时线程的最大存活时间:keepAliveTime 不能小于0
参数四:指定存活时间的单位(秒、时、分、天):unit 时间单位
参数五:指定任务队列:workQueue 不能为null
参数六:指定用哪个线程工厂创建线程:threadFactory 不能为null
参数七:指定线程忙,任务满的时候,新任务来了怎么办:handler 不能为null
临时线程什么时候创建:新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。
什么时候会开始拒绝任务:核心线程和临时线程都在忙,任务队列也满了,新的任务过来时才会开始任务拒绝。
设置线程任务
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "输出了:helloWold==>" + i);
}
}
}
自定义一个线程对象,并测试其特性
public static void main(String[] args) {
//1、创建线程池对象
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 6,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//2、给任务线程池处理
MyRunnable target = new MyRunnable();
pool.execute(target);
pool.execute(target);
pool.execute(target);
}
void execute(Runable command)
执行任务/命令,没有返回值,一般用来执行Runnable任务
void shutdown()
等任务执行完毕后关闭线程池
List
立刻关闭,停止正在执行的任务,并返回队列中执行的任务
Futer
执行任务,返回未来对象获取线程结果,一般拿来执行Callable任务
设置线程任务
public class collabledemo implements Callable<String> {
private int n;
public collabledemo(int n){
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += i;
}
return Thread.currentThread().getName() + "执行的结果是:" +sum;
}
}
自定义一个线程对象,并测试其特性
public static void main(String[] args) {
//1、创建线程池对象
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 6,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
//2、给任务线程池处理
pool.submit(new collabledemo(100));
}
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。
Executors的底层其实也是基于线程池的实现类ThreadPoolExecutor创建线程池对象的。
public static void main(String[] args) throws Exception {
// 1、创建固定线程数据的线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.execute(new MyRunnable());
pool.execute(new MyRunnable());
pool.execute(new MyRunnable());
pool.execute(new MyRunnable()); // 已经没有多余线程了
定时器是一种控制任务延时调用,或者周期调用的技术(闹钟、定时邮件发送)
public Timer()
创建Timer定时器对象
public void schedule(TimerTask ,long delay,long period)
开启一个定时器,按照计划处理TimerTask任务。
public static void main(String[] args) {
//1、创建Timer定时器
Timer timer = new Timer();//定时器本身就是一个单线程
//2、调用方法,处理定时任务
timer.schedule(new TimerTask() {
@Override
public void run() {
//这里就是延时任务的业务逻辑
System.out.println(Thread.currentThread().getName() + "执行一次--");
}
},3000,2000);
//3000为启动后3秒执行,2000是每两秒执行一次
}
1、Timer是单线程,处理多个任务按照顺序执行,存在延时与设置定时器的时间有出入。
2、可能因为其中的某个任务的异常使Timer线程死掉,从而影响后续任务的执行。
ScheduleExecutorService是JDK1.5中引入并入了并发包,目的是为了弥补Timer的缺陷, ScheduleExecutorService内部为线程池。
public static ScheduleExecutorService newScheduleThreadPool(int corePoolSize)
得到的线程池对象
public ScheduleFuture scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
周期调度方法
public static void main(String[] args) {
// 1、创建ScheduledExecutorService线程池,做定时器
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
// 2、开启定时任务
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "执行输出:AAA ==》 " + new Date());
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0, 2, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "执行输出:BBB ==》 " + new Date());
System.out.println(10 / 0);
}
}, 0, 2, TimeUnit.SECONDS);
pool.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "执行输出:CCC ==》 " + new Date());
}
}, 0, 2, TimeUnit.SECONDS);
}
基于线程池,某个任务的执行情况不会影响其他定时任务的执行。