深入学习java笔记-18.JUC-线程池
2019-05-14 本文已影响0人
笨鸡
学习目的:看MySQL索引优化时,教程需要70万测试数据,我得写一个random加线程池批量导入,节省时间。
new Thread弊端
- 每次new Thread 新建对象,性能差。
- 线程缺乏统一管理,可能无限制的新建线程,互相竞争,有可能占用过多系统资源导致死机或OOM。
- 缺少更多功能,如更多执行、定期执行、线程中断。
线程池的好处
- 重用存在的线程,减少对象创建、消亡的开销,性能佳
- 可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞
- 提供定时执行、定期执行、单线程、并发数控制等功能
线程池-ThreadPoolExecutor
线程池内部属性
- corePoolSize:核心线程数量
- maximumPoolSize:线程最大线程数
- workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响
- keepAliveTime:线程没有任务执行时最多保持多久时间终止
- unit:keepAliveTime的时间单位
- threadFactory:线程工厂,用来创建线程
- rejectHandler:当拒绝处理任务时的策略
线程池.png
线程池相关方法
- execute():提交任务,交给线程池执行。
- submit():提交任务,能够返回执行结果 execute+Future
- shutdown():关闭线程池,等待任务都执行完
- shutdownNow():关闭线程池,不等待任务执行完
- getTaskCount():线程池已执行和未执行的任务总数
- getCompletedTaskCount():已完成的任务数量
- getPoolSize():线程池当前的线程数量
- getActiveCount():当前线程池中正在执行任务的线程数量
线程池-Executor框架接口
- Executors.newCachedThreadPool
package juc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
int index = i;
executorService.execute(()-> System.out.println("task:" + index)); //直接传i报错,提示需要一个final的数据,不太理解。
}
executorService.shutdown();
}
}
- Executors.newFixedThreadPool
package juc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample2 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
int index = i;
executorService.execute(()-> System.out.println("task:" + index));
}
executorService.shutdown();
}
}
- Executors.newSingleThreadExecutor
package juc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample3 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
int index = i;
executorService.execute(()-> System.out.println("task:" + index));
}
executorService.shutdown();
}
}
- Executors.newScheduledThreadPool
package juc;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExample4 {
public static void main(String[] args) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
// for (int i = 0; i < 10; i++) {
// int index = i;
// executorService.execute(()-> System.out.println("task:" + index));
// }
// executorService.schedule(() -> System.out.println("schedule run"), 3, TimeUnit.SECONDS);
executorService.scheduleAtFixedRate(() -> System.out.println("scheduleAtFixedRate run"),
1, 3, TimeUnit.SECONDS);
// executorService.shutdown();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("TimeTask Run");
}
}, new Date(), 2 * 1000);
}
}
- ThreadPoolExecutor
StudentService studentService = ac.getBean(StudentService.class);
int corePoolSize = 2;
int maximumPoolSize = 16;
long keepAliveTime = 30;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(30);
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime,
unit, workQueue, new ThreadPoolExecutor.CallerRunsPolicy());
executor.prestartAllCoreThreads(); // 预启动所有核心线程
for (int i = 0; i < 700000; i++) {
// studentService.insertClass();
executor.execute(()->studentService.insertClass());
}
// 线程池水深,我还得好好学习内部的参数配置与原理。
线程池-合理配置
- CPU密集型任务,就需要尽量压榨CPU,参考值可以设为NCPU+1
- IO密集型任务,参考值可以设置为2*NCPU