优化资源的使用 -->池化技术
线程池、连接池、内存池、对象池。。。(创建和销毁十分浪费资源)
池化技术:事先贮备好一些资源,要用,就来这里拿,用完之后还回来
线程池的好处:
降低资源的消耗
提高的响应速度
方便管理
线程复用,可以控制最大并发数、管理线程
一、三大方法
1、newSingleThreadExecutor() 单个线程
package com.han.demo01;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestThreadPool {
public static void main(String[] args) {
ExecutorService ThreadPool1 = Executors.newSingleThreadExecutor();
//ExecutorService ThreadPool2 = Executors.newFixedThreadPool(5);
//ExecutorService ThreadPool3 = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 20; i++) {
ThreadPool1.execute(() -> {
System.out.println(Thread.currentThread().getName() + "->执行");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
ThreadPool1.shutdown();
}
}
}
2、newFixedThreadPool(int nThreads) 固定线程池大小
package com.han.demo01;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestThreadPool {
public static void main(String[] args) {
//ExecutorService ThreadPool1 = Executors.newSingleThreadExecutor();
ExecutorService ThreadPool2 = Executors.newFixedThreadPool(5);
//ExecutorService ThreadPool3 = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 20; i++) {
ThreadPool2.execute(() -> {
System.out.println(Thread.currentThread().getName() + "->执行");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
ThreadPool2.shutdown();
}
}
}
3、newCachedThreadPool() 可伸缩的,遇强则强,遇弱则弱
package com.han.demo01;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestThreadPool {
public static void main(String[] args) {
//ExecutorService ThreadPool1 = Executors.newSingleThreadExecutor();
//ExecutorService ThreadPool2 = Executors.newFixedThreadPool(5);
ExecutorService ThreadPool3 = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 20; i++) {
ThreadPool3.execute(() -> {
System.out.println(Thread.currentThread().getName() + "->执行");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
ThreadPool3.shutdown();
}
}
}
二、利用原生ThreadPoolExecutor自己创建线程池
三大方法的本质都是利用ThreadPoolExecutor创建线程池
创建线程池的七大参数:
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大小线程池大小
long keepAliveTime, //存活时间,超时了没有调用就会释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂,创建线程的,一般不用动
RejectedExecutionHandler handler //拒绝策略
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
手动创建线程池:
package com.han.demo01;
import java.util.concurrent.*;
public class TestThreadPool {
public static void main(String[] args) {
ExecutorService ThreadPool = new ThreadPoolExecutor(
2,
5,
3L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//默认的拒绝策略,不处理该请求,并抛出异常
);
try {//最大承载:阻塞队列长度+maximumPoolSize,这里是8,那么第9个请求会使用拒绝策略处理
for (int i = 1; i <= 9; i++) {
ThreadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "->执行");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
ThreadPool.shutdown();
}
}
}
pool-1-thread-1->执行
pool-1-thread-2->执行
pool-1-thread-1->执行
pool-1-thread-2->执行
pool-1-thread-1->执行
pool-1-thread-3->执行
pool-1-thread-4->执行
pool-1-thread-5->执行
java.util.concurrent.RejectedExecutionException: Task com.han.demo01.TestThreadPool$$Lambda$1/4952965@19a45b3 rejected from java.util.concurrent.ThreadPoolExecutor@99a589[Running, pool size = 5, active threads = 3, queued tasks = 0, completed tasks = 5]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at com.han.demo01.TestThreadPool.main(TestThreadPool.java:18)
只处理了8个请求,第9个请求没有处理,直接抛出异常。
三、四种拒绝策略
1. 队列满了,线程数达到最大线程数,还有线程过来,不处理这个线程,抛出异常
new ThreadPoolExecutor.AbortPolicy()
2. 哪里来的就去哪里,让调用线程去处理,比如这里的第9个请求会被主线程处理
new ThreadPoolExecutor.CallerRunsPolicy()
3. 队列满了,丢掉任务,不会抛出异常
new ThreadPoolExecutor.DiscardPolicy()
4. 队列满了,尝试和最早的竞争,竞争失败丢掉任务,也不会抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy()