线程池:
① 定长
/**
* 定长线程池5个线程,100个线程要运行,5个满了就进入队列
* 如果一个线程完了,那么线程放入线程池中不会消失,新的又进来运行了
*/
public class Fixed {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(5);
for (int i = 0; i < 100; i++) {
try {
TimeUnit.MICROSECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
es.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
// 关闭线程池
es.shutdown();
}
}
// es.shutdownNow(); // 直接关闭
// es.isTerminated();// 是否都执行完
// es.isShutdown(); // 是否关闭了,并不代表执行完
② 缓存弹性
/**
* 缓存:刚开始一个线程都没有,来一个任务起一个线程
* 此时来第二个线程,若第一个空闲则占用,第一个在运
* 行则新创建。最大是Integer.MAX_VALUE
* 默认的话,一个线程空闲超过一分钟,线程销毁。
*/
public class Cached {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
es.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
es.shutdown();
}
}
③ 单例
/**
* 单例
* 核心线程:1
* 最大线程:1
* 保证执行顺序
*/
public class Single {
public static void main(String[] args) {
ExecutorService es = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100; i++) {
es.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
}
}
④ 定时
/**
* 定时执行,自己设定核心线程数
*/
public class Schedule {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);
ses.scheduleAtFixedRate(()->{
System.out.println(Thread.currentThread().getName());
},0,500, TimeUnit.MICROSECONDS); // 第一个0秒后开始,之后经过多久执行
}
}
⑤ 精灵线程
// 本质上和ForkJoinPool是同一个线程池
// 维护的池任务列比较长,执行完直接结束不合适,精灵线程自己去拿
public class WorkStealing {
public static void main(String[] args) throws IOException {
ExecutorService es = Executors.newWorkStealingPool();
// 查看CPU几核 4 , WorkStealingPool默认起4个线程
System.out.println(Runtime.getRuntime().availableProcessors());
es.execute(new R(1000)); // 进入等待,哪个空了就自己来拿
es.execute(new R(2000));
es.execute(new R(2000));
es.execute(new R(2000));
es.execute(new R(2000)); // 第五个等着,第五个任务一定是第一个线程去运行
// 精灵线程是daemon线程,主函数main一旦结束,后台可能还在运行,但是看不到输出
// 由于产生的是精灵线程(守护线程、后台线程),主线程不阻塞的话看不到输出
System.in.read();
}
static class R implements Runnable{
int time; // 睡多久,打印当前线程名称
R(int t){
this.time = t;
}
@Override
public void run() {
try {
TimeUnit.MICROSECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(time+""+Thread.currentThread().getName());
}
}
}
⑥ ForkJoin
public class ForkJoin {
// 100万个数做一个总和
static int[] nums = new int[1000000];
static final int MAX_NUM = 50000; // 每一个小任务最多不超过5万个
static Random r = new Random();
// 方式一
static {
for (int i = 0; i < nums.length; i++) {
nums[i] = r.nextInt(100);
}
System.out.println(Arrays.stream(nums).sum()); // Java8中的String api
}
// // 方式二,使用ForkJoin递归,没有返回值,没计算结果
// static class AddTask extends RecursiveAction{
//
// int start,end;
// AddTask(int start,int end){
// this.start = start;
// this.end = end;
// }
// @Override
// protected void compute() {
// // 如果在50000个以内
// if((end - start) <= MAX_NUM){
// long sum = 0L;
// for (int i = start; i < end; i++) sum += nums[i];
// System.out.println("from:"+start+"to:"+end+"="+sum);
// }else {
// // 如果大于50000个,二分法拆分,递归
// int middle = start + (end - start)/2;
// AddTask task1 = new AddTask(start, middle);
// AddTask task2 = new AddTask(middle, end);
// task1.fork(); // task1全部递归完换task2
// task2.fork();
// }
// }
// }
// 使用RecursiveTask,返回值,泛型
static class AddTask extends RecursiveTask{
int start, end;
AddTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if(end - start <= MAX_NUM){
long sum = 0L;
for (int i = start; i < end; i++) sum += nums[i];
return sum;
}else {
// 如果大于50000个,二分法拆分,递归
int middle = start + (end - start)/2;
AddTask task1 = new AddTask(start, middle);
AddTask task2 = new AddTask(middle, end);
task1.fork();
task2.fork();
return task1.join() + task2.join();
}
}
}
public static void main(String[] args) throws IOException {
ForkJoinPool fjp = new ForkJoinPool();
AddTask task = new AddTask(0, nums.length);
fjp.execute(task);
Long result = task.join();
System.out.println(result);
// System.in.read();
}
}