线程池的创建分为两大类方法
- 通过Executors自动创建
- 通过ThreadPoolExecutor手动创建
Executors创建线程池的方法——6种
- newFixedThreadPool:创建一个固定大小的线程池
public class ThreadPool1 {
public static void main(String[] args) {
//1.创建一个大小为5的线程池
ExecutorService threadPool= Executors.newFixedThreadPool(5);
//2.使用线程池执行任务一
for (int i=0;i<5;i++){
//给线程池添加任务
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程名"+Thread.currentThread().getName()+"在执行任务1");
}
});
}
//2.使用线程池执行任务二
for (int i=0;i<8;i++){
//给线程池添加任务
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程名"+Thread.currentThread().getName()+"在执行任务2");
}
});
}
}
}
结果:
- newCachedThreadPool:带缓存的线程池,适用于短时间有大量任务的场景,但有可能会占用更多的资源;线程数量随任务量而定。
public class ThreadPool3 {
public static void main(String[] args) {
//创建线程池
ExecutorService service= Executors.newCachedThreadPool();
//有50个任务
for(int i=0;i<50;i++){
int finalI = i;
service.submit(()->{
System.out.println(finalI +"线程名"+Thread.currentThread().getName());//线程名有多少个,CPU就创建了多少个线程
});
}
}
}
结果:
执行了两次:一次有18个线程,一次有19个线程;线程的数量由cpu根据任务量而定。
- newSingleThreadExecuto:创建单个线程的线程池
创建单个线程的线程池?为啥不直接创个线程?
- 线程池的优点:
- 1.复用线程:不必频繁创建销毁线程
- 2.也提供了任务队列和拒绝策略
public class ThreadPool4 {
public static void main(String[] args) {
ExecutorService service= Executors.newSingleThreadExecutor();
for (int i=0;i<5;i++){
int finalI = i;
service.submit(()->{
System.out.println(finalI +"线程名"+Thread.currentThread().getName());//CPU只创建了1个线程,名称始终一样
});
}
}
}
结果:
- newSingleThreadScheduledExecutor:创建执行定时任务的单个线程的线程池
public class ThreadPool5 {
public static void main(String[] args) {
ScheduledExecutorService service= Executors.newSingleThreadScheduledExecutor();
System.out.println("添加任务:"+ LocalDateTime.now());
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+LocalDateTime.now());
}
},3,TimeUnit.SECONDS);//推迟3秒执行任务
}
}
结果:时间相差 3s
- newScheduledThreadPool:创建执行定时任务的线程池
/**
* 创建执行定时任务的线程池
*/
public class ThreadPool6 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(5);//5个线程
System.out.println("添加任务:" + LocalDateTime.now());
//once(service);
many(service);
}
/**
* 执行一次的定时任务
*/
public static void once(ScheduledExecutorService service) {
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+ LocalDateTime.now());
}
},3, TimeUnit.SECONDS);//推迟3秒执行
}
}
执行一次的定时任务 的结果:
当执行多次的定时任务——scheduleWithFixedDelay
//2.推迟3秒执行;上一次任务结束2s后,下一个任务开始执行
service.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+ LocalDateTime.now()+"线程名"+Thread.currentThread().getName());
try {
Thread.sleep(1000*2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},3,2,TimeUnit.SECONDS);//间隔时间成了4s;因为线程休眠了2s
当执行多次的定时任务——scheduleAtFixedRate
//1.推迟3秒执行;上一次任务开始2s后,下一个任务开始执行
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:"+ LocalDateTime.now()+"线程名"+Thread.currentThread().getName());
try {
//1.间隔时间>执行时间;以间隔时间为准
Thread.sleep(100);
//2.执行时间>间隔时间;以执行时间为准
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},3,2,TimeUnit.SECONDS);
1.间隔时间2s>执行时间0.1s;以间隔时间为准
2.执行时间3s>间隔时间2s;以执行时间为准
- newWorkStealingPool:根据当前设备的配置自动生成线程池
public class ThreadPool7 {
public static void main(String[] args) {
ExecutorService service= Executors.newWorkStealingPool();
for(int i=0;i<50;i++){
int finalI = i;
service.submit(()->{
System.out.println(finalI +"线程名"+Thread.currentThread().getName());//线程名有多少个,CPU就创建了多少个线程
});
}
//创建的为守护线程,JVM不会等待守护线程结束
while (!service.isTerminated()){
}
}
}
根据自身电脑配置决定创建的线程数目
ThreadPoolExecutor——7.手动创建线程池
public class ThreadPool9 {
public static void main(String[] args) {
//线程工厂
ThreadFactory factory=new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread=new Thread(r);
return thread;
}
};
//手动创建线程池
ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2), factory,
//1.提示异常,拒绝执行多余的任务
// new ThreadPoolExecutor.AbortPolicy()
//2.忽略堵塞队列中最旧的任务
//new ThreadPoolExecutor.DiscardOldestPolicy()
//3.忽略最新的任务
//new ThreadPoolExecutor.DiscardPolicy()
//4.使用调用该线程池的线程来执行任务
//new ThreadPoolExecutor.CallerRunsPolicy()
//5.A自定义拒绝策略
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("拒绝策略");
}
}
);
//任务
for (int i=0;i<7;i++){
int finalI=i;
threadPoolExecutor.submit(()->{
try {
Thread.sleep(finalI*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"任务名"+finalI);
});
}
}
}
7种参数分别是:
-
核心(最少)线程数
-
最大线程数
-
闲置可存活时间
-
描述(闲置可存活时间)的单位
-
任务队列
-
线程工厂
-
拒绝策略有5种:
//1.提示异常,拒绝执行多余的任务 // new ThreadPoolExecutor.AbortPolicy() //2.忽略堵塞队列中最旧的任务 //new ThreadPoolExecutor.DiscardOldestPolicy() //3.忽略最新的任务 //new ThreadPoolExecutor.DiscardPolicy() //4.使用调用该线程池的线程来执行任务 //new ThreadPoolExecutor.CallerRunsPolicy() //5.自定义拒绝策略 new RejectedExecutionHandler()
相关文章
暂无评论...