多线程
1.为什么需要使用到多线程
采用多线程的形式执行代码,目的就是为了提高程序的效率。
2.并行/串行区别
串行也就是单线程执行 代码执行效率非常低,代码从上向下执行;
并行就是多个线程并行一起执行,效率比较高。
3.多线程的使用场景
- 1.异步发送短信/发送邮件
2.异步写入日志 日志框架底层
3.将执行比较耗时的代码改用多线程异步执行; 可以提高接口的响应速度
4.多线程下载
4.多线程的创建方式
- 继承Thread类创建线程
/**
* @desc: 继承Thread类创建线程
* @author: xhs
* @date: 2021/7/5 14:46
* @version: JDK 1.8
*/
@Slf4j
public class Thread1 extends Thread {
@Override
public void run() {
log.info(">>>>>>>>>>>>>>继承Thread类创建线程:{},我是子线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
}
public static void main(String[] args) {
log.info(">>>>>>>>>>>>>>继承Thread类创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
Thread1 thread1 = new Thread1();
// 启动线程是start方法而不是run方法
thread1.start();
log.info(">>>>>>>>>>>>>>继承Thread类创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
}
}
- 实现Runnable接口创建线程
/**
* @desc: 实现Runnable接口创建线程
* @author: xhs
* @date: 2021/7/5 14:53
* @version: JDK 1.8
*/
@Slf4j
public class Thread2 implements Runnable {
@Override
public void run() {
log.info(">>>>>>>>>>>>>>实现Runnable接口创建线程:{},我是子线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
}
public static void main(String[] args) {
log.info(">>>>>>>>>>>>>>实现Runnable接口创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
Thread thread = new Thread(new Thread2());
thread.start();
log.info(">>>>>>>>>>>>>>实现Runnable接口创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<",Thread.currentThread().getName());
}
}
- 使用匿名内部类的形式创建线程
/**
* @desc: 使用匿名内部类的形式创建线程
* @author: xhs
* @date: 2021/7/5 14:57
* @version: JDK 1.8
*/
@Slf4j
public class Thread3 {
public static void main(String[] args) {
log.info(">>>>>>>>>>>>>>使用匿名内部类的形式创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
new Thread(new Runnable() {
public void run() {
log.info(">>>>>>>>>>>>>>使用匿名内部类的形式创建线程:{},我是子线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
}).start();
log.info(">>>>>>>>>>>>>>使用匿名内部类的形式创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
}
- 使用lambda表达式创建线程
/**
* @desc: 使用lambda表达式创建线程
* @author: xhs
* @date: 2021/7/5 15:00
* @version: JDK 1.8
*/
@Slf4j
public class Thread4 {
public static void main(String[] args) {
log.info(">>>>>>>>>>>>>>使用lambda表达式创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
new Thread(() ->{
log.info(">>>>>>>>>>>>>>使用lambda表达式创建线程:{},我是子线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}).start();
log.info(">>>>>>>>>>>>>>使用lambda表达式创建线程:{},我是主线程<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
}
- 使用Callable和Future创建线程
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @desc: 使用Callable和Future创建线程
* @author: xhs
* @date: 2021/7/5 15:03
* @version: JDK 1.8
*/
@Slf4j
public class Thread5 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
log.info(">>>>>>>>>>>>>>使用Callable和Future创建线程,我是子线程:{},返回结果为100<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
return 100;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
log.info(">>>>>>>>>>>>>>使用Callable和Future创建线程,我是主线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
Thread5 threadCallable = new Thread5();
FutureTask<Integer> integerFutureTask = new FutureTask<>(threadCallable);
new Thread(integerFutureTask).start();
Integer result = integerFutureTask.get();
log.info(">>>>>>>>>>>>>>我是主线程:{},拿到子线程的返回结果为:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName(), result);
}
}
- 使用线程池例如用Executor框架
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @desc: 使用线程池Executor框架
* @author: xhs
* @date: 2021/7/5 15:11
* @version: JDK 1.8
*/
@Slf4j
public class Thread6 {
public static void main(String[] args) {
log.info(">>>>>>>>>>>>>>使用线程池Executor框架创建线程,我是主线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
log.info(">>>>>>>>>>>>>>使用线程池Executor框架创建线程,我是子线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
});
log.info(">>>>>>>>>>>>>>使用线程池Executor框架创建线程,我是主线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
}
- spring @Async异步注解
需要在springBoot启动类上开启异步注解
异步执行代码管理层
需要注入到spring容器中
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* @desc: 使用Spring的@Async异步注解创建多线程
* @author: xhs
* @date: 2021/7/5 15:14
* @version: JDK 1.8
*/
@Slf4j
@Component
public class Thread7 {
@Async
public void asyncLog() {
log.info(">>>>>>>>>>>>>>使用Spring的@Async异步注解创建多线程,我是子线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
}
}
控制层
@Slf4j
@RestController
public class TestAsync {
@Autowired
private Thread7 thread7;
@GetMapping("/getName")
public String getName(){
log.info(">>>>>>>>>>>>>>使用Spring的@Async异步注解创建多线程,我是主线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
thread7.asyncLog();
log.info(">>>>>>>>>>>>>>使用Spring的@Async异步注解创建多线程,我是主线程:{}<<<<<<<<<<<<<<<<<<<<", Thread.currentThread().getName());
return "success";
}
}
启动类
@EnableAsync // 开启异步注解
@SpringBootApplication
public class ThreadDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ThreadDemoApplication.class, args);
}
}
源码地址:https://gitee.com/xhs101/tools-parent/tree/master/thread-server