一、使用ThreadPoolTaskExecutor创建线程池

这个类则是spring包下的,是sring为我们提供的线程池类

1、线程词配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

// 线程词配置类
@Configuration
//开启异步调用, 即哪个方法用了 @Async("taskExecutor"),就会通过线程池调用
@EnableAsync
public class TaskPoolConfig {

    @Bean(name="taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数:就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收
        executor.setCorePoolSize(6);
        //配置最大线程数:就是线程池中可以容纳的最大线程的数量
        executor.setMaxPoolSize(20);
        //配置队列大小
        executor.setQueueCapacity(300);
        //线程池维护线程所允许的空闲时间:就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间
        executor.setKeepAliveSeconds(60);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("task-executor-");

        // handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // AbortPolicy:用于被拒绝任务的处理程序,它将抛出RejectedExecutionException
        // CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务。
        // DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试execute。
        // DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
        
        //执行初始化
        executor.initialize();
        return executor;
    }
}

2、使用

显式使用:

@Autowired
    @Qualifier("taskExecutor")  //指定某个bean
    private Executor taskExecutor;

    // 显式调用线程池
    @GetMapping("testPool")
    @ApiOperation(value = "查找",notes = "显式调用线程池的线程,异步执行方法")
    public ResponseResult testPool() {
        taskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < 20; i++) {
                        Thread.sleep(200);
                        System.out.println("异步执行testPool(),  i = " + i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        return ResponseResult.success("后台在执行中,先返回数据给你");
    }

隐式使用:

@Async("taskExecutor")    // 这个注解是将此方法交给线程池里的线程来运行
    public void testThreadPool() {
        try {
            Thread.sleep(1000);
            System.out.println(" 多线程执行 " + currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

// 异步也可以返回Future内容,Future.get()可以取出future里的内容
    @Async
    public Future<String> asyncInvokeReturnFuture(int i) {
    Future<String> future;
    try {
        Thread.sleep(1000 * 1);
        future = new AsyncResult<String>("success:" + i);
    } catch (InterruptedException e) {
        future = new AsyncResult<String>("error");
    }
    return future;

 

二、直接使用原生线程池 

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) ;

ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 20, 2,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),new ThreadPoolExecutor.CallerRunsPolicy());

 

三、Executors工厂方法创建线程池(少用)

 

//创建使用单个线程的线程池
        ExecutorService es1 = Executors.newSingleThreadExecutor();

//创建使用固定线程数的线程池
        ExecutorService es2 = Executors.newFixedThreadPool(3);

 //创建一个会根据需要创建新线程的线程池
        ExecutorService es3 = Executors.newCachedThreadPool();

 //创建拥有固定线程数量的定时线程任务的线程池
        ScheduledExecutorService es4 = Executors.newScheduledThreadPool(2);

//创建只有一个线程的定时线程任务的线程池
        ScheduledExecutorService es5 = Executors.newSingleThreadScheduledExecutor();