久久建筑网和恒智天成那个软件好,seoul是什么意思中文,WordPress无刷新登录,网站需要多大数据库文章目录 整体描述实现方法一、注解Async1. 添加注解2. 创建异步方法Service和实现类3. 调用异步方法 二、AsyncManager1. 创建AsyncManager类2. 创建一个耗时的操作类3. 执行异步操作 三、线程池1. 创建线程池2. 创建一个耗时的操作类3. 执行线程池 总结 整体描述
在java中异… 文章目录 整体描述实现方法一、注解Async1. 添加注解2. 创建异步方法Service和实现类3. 调用异步方法 二、AsyncManager1. 创建AsyncManager类2. 创建一个耗时的操作类3. 执行异步操作 三、线程池1. 创建线程池2. 创建一个耗时的操作类3. 执行线程池 总结 整体描述
在java中异步线程很重要比如在业务流处理时需要通知硬件设备发短信通知用户或者需要上传一些图片资源到其他服务器这种耗时的操作在主线程里处理会阻塞整理流程而且我们也不需要等待处理结果之后再进行下一步操作这时候就可以使用异步线程进行处理这样主线程不会因为这些耗时的操作而阻塞保证主线程的流程可以正常进行。 最近在项目中使用了很多线程的操作在这做个记录。 实现方法
线程的操作是java中最重要的部分之一实现线程操作也有很多种方法这里仅介绍几种常用的。在springboot框架中可以使用注解简单实现线程的操作还有AsyncManager的方式如果需要复杂的线程操作可以使用线程池实现。下面根据具体方法进行介绍。
一、注解Async
springboot框架的注解使用时也有一些限制这个在网上也有很多介绍Async注解不能在类本身直接调用在springboot框架中可以使用单独的Service实现异步方法然后在其他的类中调用该Service中的异步方法即可具体如下
1. 添加注解
在springboot的config中添加 EnableAsync注解开启异步线程功能
package com.thcb.boot.config;import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;/*** MyConfig** author thcb*/Configuration
EnableAsync
public class MyConfig {// 自己配置的Config
}2. 创建异步方法Service和实现类
使用service实现耗时的方法
Service类
package com.thcb.execute.service;import org.springframework.scheduling.annotation.Async;/*** IExecuteService** author thcb*/
public interface IExecuteService {/*** 一些耗时的操作使用单独线程处理* 这里就简单写了一个sleep5秒的操作*/Asyncpublic void sleepingTest();
}Service实现类
package com.thcb.execute.service.impl;import com.thcb.execute.service.IExecuteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;/*** ExecuteService业务层处理** author thcb*/
Service
public class ExecuteServiceImpl implements IExecuteService {private static final Logger log LoggerFactory.getLogger(ExecuteServiceImpl.class);Overridepublic void sleepingTest() {log.info(SleepingTest start);try {Thread.sleep(5000);} catch (Exception e) {log.error(SleepingTest: e.toString());}log.info(SleepingTest end);}
}3. 调用异步方法
这里根据Springboot的框架在controller层调用并使用log查看是否时异步结果。
controller
package com.thcb.boot.controller;import com.thcb.execute.service.IExecuteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** TestController** author thcb*/
RestController
public class TestController {private static final Logger log LoggerFactory.getLogger(TestController.class);Autowiredprivate IExecuteService executeService;RequestMapping(/test)public String test() {return spring boot;}RequestMapping(/executeTask)public String executeTask() {log.info(executeTask Start!);executeService.sleepingTest();log.info(executeTask End!);return executeTask;}
}在log查看结果 接口直接返回了executeTask并log出executeTask End在5秒之后log打出SleepingTest end说明使用了异步线程处理了executeService.sleepingTest的方法。
二、AsyncManager
使用AsyncManager方法也是SpringBoot框架中带的任务管理器可以实现异步线程。
1. 创建AsyncManager类
使用AsyncManager首先需要创建一个AsyncManager类这个在springboot框架中应该也是有的
/*** 异步任务管理器** author thcb*/
public class AsyncManager {/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME 10;/*** 异步操作任务调度线程池*/private ScheduledExecutorService executor SpringUtils.getBean(scheduledExecutorService);/*** 单例模式*/private AsyncManager() {}private static AsyncManager me new AsyncManager();public static AsyncManager me() {return me;}/*** 执行任务** param task 任务*/public void execute(TimerTask task) {executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown() {Threads.shutdownAndAwaitTermination(executor);}
}2. 创建一个耗时的操作类
这里同样需要创建一个耗时的操作也是用sleep模拟
public TimerTask sleepingTest() {return new TimerTask() {Overridepublic void run() {// 耗时操作try {Thread.sleep(5000);} catch (Exception e) {log.error(SleepingTest: e.toString());}}};
}3. 执行异步操作
使用AsyncManager执行异步操作也比较简单直接调用即可
// 异步线程池
AsyncManager.me().execute(sleepingTest());三、线程池
使用线程池可以设定更多的参数线程池在网上也有很多详细的介绍在这我只介绍一种带拒绝策略的线程池。
1. 创建线程池
创建带有拒绝策略的线程池并设定核心线程数最大线程数队列数和超出核心线程数量的线程存活时间
/*** 线程池信息 核心线程数量5最大数量10队列大小20超出核心线程数量的线程存活时间30秒 指定拒绝策略的*/
private static final ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(5, 10, 30, TimeUnit.SECONDS,new LinkedBlockingQueueRunnable(20), new RejectedExecutionHandler() {Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {log.error(有任务被拒绝执行了);}
});2. 创建一个耗时的操作类
由于线程池需要传入一个Runnable所以此类继承Runnable还是用sleep模拟耗时操作。
/*** 耗时操作*/
static class MyTask implements Runnable {private int taskNum;public MyTask(int num) {this.taskNum num;}Overridepublic void run() {System.out.println(正在执行task taskNum);try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(task taskNum 执行完毕);}
}3. 执行线程池
开启线程池这里通过一个for循环模拟一下可以看一下log输出有兴趣的可以修改一下for循环和sleep的数值看看线程池具体的操作和拒绝流程。
for (int i 0; i 20; i) {MyTask myTask new MyTask(i);threadPoolExecutor.execute(myTask);System.out.println(线程池中线程数目 threadPoolExecutor.getPoolSize() 队列中等待执行的任务数目 threadPoolExecutor.getQueue().size() 已执行完别的任务数目 threadPoolExecutor.getCompletedTaskCount());
}
threadPoolExecutor.shutdown();总结
在此写一些线程操作需要注意的地方
线程数量和cpu有关使用线程时一定要注意线程的释放否则会导致cpu线程数量耗尽使用注解完成的线程操作不可以在自己的类中实现调用因为注解最后也是通过代理的方式完成异步线程的最好时在单独的一个service中写线程池最好单独写使用static和final修饰保证所有使用该线程池的地方使用的是一个线程池而不能每次都new一个线程池出来每次都new一个就没有意义了。
以上就是三种线程池的操作写的不算很详细有兴趣的同学可以自己在深入研究一下。