自定义线程工厂
public class CustomThreadFactory implements ThreadFactory {
//静态变量 记录当前创建的自定义线程工厂数 使用原子类,保证操作的原子性
private static final AtomicInteger poolNumber = new AtomicInteger(1);
//记录每个自定义线程工厂的线程数
private final AtomicInteger threadNumber = new AtomicInteger(1);
//设置线程工厂名,在创建线程的时候
private final String namePrefix;
//构造函数 poolNumber.getAndIncrement(),自定义线程工厂数加一,并设置这个线程工厂的工厂名,在创建线程的时候,加上工厂名
public CustomThreadFactory(String threadNamePrefix) {
namePrefix = threadNamePrefix + "-" + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
return t;
}
}
自定义线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 100
, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),Executors.defaultThreadFactory());
// 这里使用的是Executors提供的默认线程工厂,默认的线程工厂跟我自定义的线程工厂几乎没有区别,但是默认的线程工厂只有空参构 //造。无法对线程工厂创建的线程添加前缀
//使用自定义的线程工厂只需要将最后一个参数替换成 new CustomThreadFactory(”myfactory“)
//自定义线程池的参数
int corePoolSize //线程池的核心线程数量
int maximumPoolSize,//线程池的最大线程数
long keepAliveTime,//当线程数大于核心线程数时,多余的空闲线程存活的最长时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列,用来储存等待执行任务的队列
ThreadFactory threadFactory,//线程工厂,用来创建线程
RejectedExecutionHandler handler//拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务
如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,将会执行拒绝策略
ThreadPoolExecutor 定义一些策略:
ThreadPoolExecutor.AbortPolicy:抛出 RejectedExecutionException来拒绝新任务的处理。
ThreadPoolExecutor.CallerRunsPolicy:调用执行自己的线程运行任务,也就是直接在调用execute方法的线程中运行(run)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果你的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。
ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉。
ThreadPoolExecutor.DiscardOldestPolicy:此策略将丢弃最早的未处理的任务请求。
举个例子:Spring 通过 ThreadPoolTaskExecutor 或者我们直接通过 ThreadPoolExecutor 的构造函数创建线程池的时候,当我们不指定 RejectedExecutionHandler 拒绝策略来配置线程池的时候,默认使用的是 AbortPolicy。在这种拒绝策略下,如果队列满了,ThreadPoolExecutor 将抛出 RejectedExecutionException 异常来拒绝新来的任务 ,这代表你将丢失对这个任务的处理。如果不想丢弃任务的话,可以使用CallerRunsPolicy。CallerRunsPolicy 和其他的几个策略不同,它既不会抛弃任务,也不会抛出异常,而是将任务回退给调用者,使用调用者的线程来执行任务。
使用自定义线程池,自定义线程工厂开启异步任务
//1.使用CompletableFuture开启异步任务,有返回值
List<Integer> test=new ArrayList<>();
test.add(1);
test.add(2);
test.add(3);
//map(Function<? super T, ? extends R> mapper) 传入的是一个函数式接口 T为传入参数类型,R为返回参数类型
//此处values就是我们的传入参数,supplyAsync的结果就是返回值,supplyAsync的返回值为Completable<value>类型,map的多个结果需要放入list中
List<CompletableFuture<Integer>> completableFutureList = test.stream().map(value->CompletableFuture.supplyAsync(()->{
return value*2;},executor)).collect(Collectors.toList());
//获取异步任务的结果
for (CompletableFuture<Integer> future : completableFutureList) {
System.out.println(future.get());
}
//2.使用线程池直接开启一个异步任务,无返回值
executor.execute(() -> {
System.out.println("我是自定义线程池" + Thread.currentThread().getName());
//输出 我是自定义线程池-myfactory-thread-1 ,thread-1指的就是线程1
});
//注意lamdal表达式的格式 隐式返回:e->value 显式返回: 需要加上大括号,分号,return;