Java和Spring中线程池创建方法 |
您所在的位置:网站首页 › java创建线程的方法和区别 › Java和Spring中线程池创建方法 |
一、线程池定义
1.JDK中线程池类图
Executor:父接口,所有线程池都实现了这个接口,里面有一个excute()方法用于执行线程 ExecutorService:线程池接口,继承自Executor接口,供了生命周期管理的方法,返回 Future 对象,可以返回执行完的结果 ThreadPoolExecutor:线程池的具体实现类,一般使用ThreadPoolExecutor创建线程池 2.创建线程池的工具类 Executors:线程池的工具类,用于创建线程池,返回ExecutorService类型的线程池 1)public static ExecutorService newFiexedThreadPool(int Threads) :创建固定数目线程的线程池 2)public static ExecutorService newCachedThreadPool():创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程 3)public static ExecutorService newSingleThreadExecutor():创建一个单线程化的Executor 4)public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):调度型线程池 3.区别1)Executor 接口定义了 execute()方法用来接收一个Runnable接口的对象,不接受返回的对象,而 ExecutorService 接口中的 submit()方法可以通过Future 对象接受Runnable和Callable接口的对象 2)ExecutorService 还提供用来控制线程池的方法。比如:调用 shutDown() 方法终止线程池 3)Executors 类提供工厂方法用来创建不同类型的线程池 4.线程池参数corePoolSize:核心线程数 maximumPoolSize, //最大线程数 keepAliveTime:当线程数超过核心线程数,线程的最大存活时间 unit:keepAliveTime的时间单位 workQueue:阻塞队列 threadFactory: 创建线程的工厂 handler:拒绝策略 5.线程池执行顺序1)当线程数小于 corePoolSize时,创建线程执行任务。 2)当线程数大于等于 corePoolSize并且 workQueue 没有满时,放入workQueue中 3)线程数大于等于 corePoolSize并且当 workQueue 满时,新任务新建线程运行,线程总数要小于 maximumPoolSize 4)当线程总数等于 maximumPoolSize 并且 workQueue 满了的时候执行 handler 的 rejectedExecution。也就是拒绝策略 6.拒绝访问策略ThreadPoolExecutor默认有四个拒绝策略: 1、ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException 2、ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行 3、ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务 4、ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务 当然可以自己继承RejectedExecutionHandler来写拒绝策略. 二、线程池使用方法 1.Java JDK创建线程池的方法-ThreadPoolExecutor 1)使用ThreadPoolExecutor创建线程池 API如下所示: public ThreadPoolExecutor(int corePoolSize, //核心线程数 int maximumPoolSize, //最大线程数 long keepAliveTime, //当线程数超过核心线程数,线程的最大存活时间 TimeUnit unit, //keepAliveTime的时间单位 BlockingQueue workQueue) //阻塞队列容量 { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }所在包:java.util.concurrent.* 2)代码实现: 3)结果展示:
所在包:package org.springframework.core.task; 创建线程池并注入spring容器,开启@EnableAsync注解方便后续使用它@Async异步化调用 @Configuration @EnableAsync public class BeanConfig { @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 设置核心线程数 executor.setCorePoolSize(5); // 设置最大线程数 executor.setMaxPoolSize(10); // 设置队列容量 executor.setQueueCapacity(20); // 设置线程活跃时间(秒) executor.setKeepAliveSeconds(60); // 设置默认线程名称 executor.setThreadNamePrefix("hello-"); // 设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } } 3.异步调用线程池线程方法-ThreadPoolTaskExecutor 1)代码处使用 需要使用@Autowired装配获取注入的线程池对象 @Autowired private ThreadPoolTaskExecutor executor; /** * 根据活动id获取指定活动,异步添加缓存操作 */ @RequestMapping("/test9") public String testTaskExecutor() throws Throwable { log.info("进入方法:"); //异步调用 executor.execute(() -> { try { log.info("进入异步方法:"); Thread.sleep(2000); jedisClusterClient.getJedisCluster().set("test9:async", "test"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步执行添加缓存:" + jedisClusterClient.getJedisCluster().get("test9:async")); }); log.info("方法执行完毕"); return "test"; }执行结果: 可以看到异步执行是在方法执行完毕后才执行的,不是同步的,异步化成功 2)使用@Async注解异步调用 注意:@Async修饰的方法的实例必须注入spring容器中方能使用,代码如下: 异步方法使用@Async调用: 执行结果: 可以看到结果也是异步化调用 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |