继承创建
通过继承Thread来创建线程,由于java的单继承性,对子类的限制比较多,子类结构也会比较单一,大多是业务场景并不适用这个方案。
/**
* @Project: MySpringBoot
* @Package: com.example.demo.common.utils.async
* @ClassName: MyThread
* @Description: TODO
* @Author: xueyujiao
* @Date: 2024/3/7
* @Version 1.0
*/
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("重写父类的run方法!");
}
}
// 调用
MyThread myThread = new MyThread();
myThread.start();
实现接口创建
java不支持多继承,但支持多实现接口,runnable和callable提供了这种方法进行创建线程。
Runnable
/**
* @Project: MySpringBoot
* @Package: com.example.demo.common.utils.async
* @ClassName: MyRunnable
* @Description: TODO
* @Author: xueyujiao
* @Date: 2024/3/7
* @Version 1.0
*/
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println( name + "runnable 执行!");
}
}
Callable
callable与runnable的不同是,callable可以自定义返回值。
/**
* @Project: MySpringBoot
* @Package: com.example.demo.common.utils.async
* @ClassName: MyCallable
* @Description: TODO
* @Author: xueyujiao
* @Date: 2024/3/7
* @Version 1.0
*/
public class MyCallable implements Callable<Map> {
private String name;
public MyCallable(String name) {
this.name = name;
}
@Override
public Map<String, String> call() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("result", "call end!" + name);
return map;
}
}
线程池创建
以上三种是普遍使用的三种创建线程的方式,还有一种是通过线程池来实现
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 无返回值
executorService.execute(new MyRunnable("线程池A-1"));
// 有返回值
Future<Map> submit = executorService.submit(new MyCallable("线程池A-1"));
Map<String, String> map = submit.get();
System.out.println(map);
其他方式
以上几种,底层都是基于runnable来实现的。其实还可以简化为lambda表达式:
// 创建匿名类
new Thread() {
@Override
public void run() {
System.out.println("继承Thread!");
}
}.start();
// blambda表达式
new Thread(() -> {
// 实现Runnable接口
}).start();
// 实现callable
FutureTask<String> futureTask1 = new FutureTask<String>(() ->{
return "futureTask1线程";
});
总结
在正常项目开发中,最好不要直接使用Exexutors来创建线程池,可以使用FixedThreadPool来自定义线程池。首先看一下Executors.newFixedThreadPool是如何构建线程池
若设置当前线程池固定大小为10,核心线程和最大线程为10,阻塞队列使用LinkedBlockingQueue(无界阻塞队列),之所以被称为无界队列,是由于该链表最大值为Integer.MAX_VALUE(2147483647),当线程特别多时,会不断增加到链表中,占用过多内存,最终导致OOM。
建议自定义new ThreadPoolExecutor(),传入适应项目运行的参数