多线程创建方式
1.继承Thread类
2.实现Runnalbe接口
3.使用匿名内部类
4.使用lambda表达式创建
5.使用callable和Future
6.使用线程池(juc-ThreadPoolExecutor,spring-ThreadPoolTaskExecutor)
7.spring @Async异步注解,结合线程池
线程状态:初始化-就绪-运行-死亡-阻塞-超时-等待
@Async的使用
1.aop拦截只要在方法上有使用到@ZzrAsync注解的,就单独的开启单独的异步线程去实现。
Aop:
http请求
环绕通知开始
目标方法
环绕通知结束
代码如下:
目录:
注解类:
/**
* @author Admin
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ZzrAsync {
String value() default "";
}
线程类:
@Component
@Slf4j
public class TestThread {
@ZzrAsync
public void asyncLog(){
try {
log.info("目标方法正在执行,等待5s");
Thread.sleep(5000);
Map<String, String> stringStringMap = ExThreadAsyncAop.THREAD_LOCAL_NUM.get();
System.out.println(stringStringMap);
log.info("目标方法执行完毕,等待5s结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
controller使用:
/**
* @author zzr
* @version 1.0
* @since 2020/7/20 16:39
*/
@RestController
@RequestMapping(value = "thread")
public class TestMain {
@Resource
TestThread testThread;
@RequestMapping(value = "hello")
public String hello3() {
testThread.asyncLog();
return "hello, " + 1;
}
}
AOP操作注解:
@Aspect
@Component
@Slf4j
public class ExThreadAsyncAop {
/**
* 线程本地存储变量
*/
public static final ThreadLocal<Map<String,String>> THREAD_LOCAL_NUM = new ThreadLocal<>();
/**
* 环绕通知,会拦截方法
* @param joinPoint
* @return
*/
@Around(value = "@annotation(com.example.bilibili.ZzrAsync)")
public Object around(ProceedingJoinPoint joinPoint) {
log.info("环绕通知开始执行");
// 在调用目标方法的时候使用线程即可将加了注解的方法多线程执行,如下
new Thread(() -> {
try {
Map<String, String> map = new HashMap<>();
map.put(Thread.currentThread().getName(),"testvalue"+Thread.currentThread().getName());
THREAD_LOCAL_NUM.set(map);
joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
THREAD_LOCAL_NUM.remove();
}
}).start();
// joinPoint.proceed();// 会调用aop的目标方法--即使用ZzrAsync注解的方法
log.info("环绕通知结束执行");
return "环绕通知";
}
}