--- Java 线程、线程池 --- #### 目录 1. 前言 2. 线程的创建 3. Callable 与 Future 4. 线程池 5. 参考 #### 前言 #### 线程的创建 我们知道,线程的创建有两种方式:一种是继承 Thread 类,另一种是实现 Runnable 接口。但是这两种方式有一个共同的缺陷,那就是在执行任务后无法获取执行结果(两者 run 方法的返回类型都是 void )。于是在 JDK 5 就引入了 Callable 和 Future。 #### Callable 与 Future ##### Callable ```java public interface Callable { V call() throws Exception; } ``` Callable 是一个泛型接口,你可以完全把它理解为一个有返回类型并且可抛异常的 Runnable。 那么是如何获取 Callable 的返回结果呢?通常是通过 FutureTask 这个中间媒介来实现的。 ##### FutureTask FutureTask 实现了 Runnable 和 Future 接口,所以我们可以直接用 Thread 来执行它,也可以使用 ExecuteService 来执行。这里就以 Thread 包装来执行: ```java public class ThreadDemo { public static void main(String[] args) throws Exception { Callable call = () -> { System.out.println("线程执行..."); Thread.sleep(2000); return 1; }; FutureTask task = new FutureTask<>(call); new Thread(task).start(); System.out.println(task.get()); } } ``` ##### Future Future 的核心思想是:一个方法,计算过程可能非常耗时,等待方法返回显然不可取。可以在执行方法的时候,立马就返回一个 Future 对象,通过这个 Future 对象去控制方法的计算过程。 ```java public interface Future { /** * 取消任务 */ boolean cancel(boolean mayInterruptIfRunning); /** * 判断是否取消 */ boolean isCancelled(); /** * 判断是否已完成 */ boolean isDone(); /** * 获取任务结果,如果未完成,则等待 */ V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; } ``` #### 线程池 线程池是为了线程的复用,避免重复创建和销毁线程所带来的性能损耗。 ##### ThreadPoolExecutor ThreadPoolExecutor 类是线程池中最核心的一个类,它提供了四个构造方法: ```java public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue){}; public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory){}; public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler){}; public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler){}; ``` 前面三个构造方法都是通过调用第四个构造方法来进行初始化工作的,下面解释一下各个参数的含义: - corePoolSize 核心线程的大小。在创建线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了 prestartAllCoreThreads() 或者 prestartCoreThread() 方法,从这两个方法名就可以看出,是预创建线程的意思。 #### 参考 [Java并发编程:线程池的使用](https://www.cnblogs.com/dolphin0520/p/3932921.html)