Executor
线程池可以实现线程的复用,并且可以管理线程控制线程的最大数量。
线程池简单应用
线程池中默认存储核心线程池大小的线程,如果每个核心线程都被占用,新进的线程就会进入阻塞队列等待,阻塞队列队满的时候就会开启新的线程直到线程数量为最大线程池的容量,线程池内的线程如果超过超时时间还没有线程处理就会关闭线程直到线程池内线程的数量为核心线程池的数量,如果线程池内的容量已经是最大并且阻塞队列队满的情况下还有线程进来就会启动拒绝策略拒绝线程。
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
//线程池子里面有5个线程
ExecutorService pool1 = Executors.newFixedThreadPool(5);
//线程池子里面只有1个线程
ExecutorService pool2 = Executors.newSingleThreadExecutor();
//一般使用这种方式
ThreadPoolExecutor pool3 = new ThreadPoolExecutor(
/**
* 系统的内核数目:int i1 = Runtime.getRuntime().availableProcessors();
* CPU密集型:主要的工作就是计算,i1+1
* IO密集型:主要的工作是IO操作, i1*2
*/
10, //核心线程池大小
20, //最大线程池大小
60L, //非核心线程等待的超时时间
TimeUnit.SECONDS, //超时时间单位
new SynchronousQueue<>(), //线程阻塞队列
Executors.defaultThreadFactory(), //线程工厂
/**
* CallerRunsPolicy : 会在线程池当前正在运行的Thread线程中处理被拒绝的任务
* AbortPolicy : 默认策略,抛出RejectedExecutionException
* DiscardPolicy : 不能执行的任务将被删除
* DiscardOldestPolicy : 线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中
*/
new ThreadPoolExecutor.AbortPolicy()); //拒绝策略
try {
for (int i = 0; i < 10; i++) {
pool.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
} finally {
//最后关闭线程池
pool.shutdown();
}
}
Executors
ScheduledExecutorService
线程的调度接口,可以延时执行线程。
public static void main(String[] args) {
ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(
10,
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 0; i < 10; i++) {
ScheduledFuture<?> schedule = pool.schedule(
() -> System.out.println(Thread.currentThread().getName()),
3,
TimeUnit.SECONDS);
System.out.println(schedule.get());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//最后关闭线程池
pool.shutdown();
}
}
Fork/Join
Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到结果的框架。
工作窃取模式
将大任务分割成多个小任务,每个小任务的执行时间不同,先执行完任务的线程不会阻塞,它会从当前未完成任务的线程队列中寻找一个线程,窃取它的任务。
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class Test {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Integer> task = new ForkJoin(1, 10000);
Integer result = pool.invoke(task);
System.out.println(result);
}
}
//RecursiveTask:有返回值
//RecursiveAction:没有返回值
class ForkJoin extends RecursiveTask<Integer> {
private int start;
private int end;
private int split = 100;
public ForkJoin(int start, int end) {
this.start = start;
this.end = end;
}
//会递归调用方法
@Override
protected Integer compute() {
int length = start - end;
int result = 0;
if (length < split) {
for (int i = start; i <= end; i++) {
result += i;
}
} else {
int middle = (start - end) / 2;
ForkJoin left = new ForkJoin(start, middle);
ForkJoin right = new ForkJoin(middle + 1, end);
//拆分并且压入线程队列
left.fork();
right.fork();
result = left.join() + right.join();
}
return result;
}
}