一、线程创建方式
1.继承Thread类,重写run方法
2.实现Runnable接口,实现run方法
相较于继承Thread类方式可以避免单继承局限
3.实现Callable接口,实现call方法
相较于实现Runnable接口,Callable接口提供了返回值的功能,一般配合Future接口使用,可以在任务执行完毕之后得到任务执行结果
4.通过线程池启动多线程
二、线程常用接口介绍
1.Future
Future接口为具体的Runnable或Callable任务提供了取消任务,查询任务状态,获取任务结果的功能,可以通过get()方法获取执行结果,该方法会阻塞直到任务返回结果
api:
cancel:
取消任务方法,取消成功返回true,失败返回false。参数mayInterruptIfRunning表示是否取消正在执行却没有执行完成的任务,为true时取消,false时不取消。如果任务已经完成,则返回false。
isCancelled:
返回任务是否被成功取消,若果任务完成前被取消成功,返回true
isDone:
返回任务是否完成
get:
获取执行结果,阻塞一直等到任务执行完毕
get(long timeout,TimeUnit unit):
获取执行结果,如果在指定时间内没有获取到结果,返回null。
2.FutureTask
Future接口的唯一实现类
继承关系为 FutureTask实现了RunnableFuture接口,RunnableFuture继承了Runnable和Future接口。所以FutureTask即可以作为Runnable被线程执行,也可以作为Future获取Callable的返回值
使用范例:
FutureTask+Callable
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName());
Thread.sleep(3000);
return Thread.currentThread().getName();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadTest threadTest = new ThreadTest();
FutureTask<String> futureTask = new FutureTask<>(threadTest);
Thread thread = new Thread(futureTask1);
thread.start();
System.out.println(futureTask.get());
}
}
Future+线程池
import java.util.concurrent.*;
public class FutureTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> submit = executorService.submit(() -> {
System.out.println(Thread.currentThread().getName());
return "aaa";
});
System.out.println(submit.get());
}
}
三、线程池工具类Executors(阿里java代码规范不建议使用Executors创建线程池,不直观)
Executors线程池工具可以简单的创建线程池,常用的为
- 固定线程数线程池newFixedThreadPool(int nThreads)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 - 工作窃取线程池(抢占式线程池)WorkStealingPool
- 单线程线程池 newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 - 带缓存的线程池 newCachedThreadPool
弹性的线程池线程管理,用多少线程给多大的线程池,不用后及时回收,用则新建 - 任务调度线程池 newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
四、ThreadPoolExecutor解析
此处踩的坑为maximumPoolSize只有在队列已满时才生效
参数:
参数 | 类型 | 含义 |
---|---|---|
corePoolSize | int | 核心线程池大小 |
maximumPoolSize | int | 最大线程池大小 |
keepAliveTime | long | 线程最大空闲时间 |
unit | TimeUnit | 线程最大空闲时间的单位 |
workQueue | BlockingQueue<Runnable> | 任务等待队列 |
threadFactory | ThreadFactory | 线程创建工厂 |
handler | RejectedExecutionHandler | 当线程达到最大数且任务等待队列达到最大时的拒绝策略 |
api
void allowCoreThreadTimeOut(boolean value) 设置核心线程超时时是否回收
线程创建逻辑为:
- 如果当前线程数小于核心线程数,创建新的线程执行任务
- 如果当前线程数不小于核心线程数,将任务放入任务等待队列中
- 如果任务等待队列已满,尝试创建任务线程执行任务
- 如果创建任务线程失败,根据配置的任务拒绝策略执行操作