线程池(熟悉)
1. Callable接口
<1> 从Java5开始,新增加创建线程的第三种方式:实现java.util.concurrent.Callable接口
<2> 常用方法
V call() | 计算结果并返回 |
<3> 代码示例 (ThreadCallableTest.java)
5 public class ThreadCallableTest implements Callable { 6 7 @Override 8 public Object call() throws Exception { 9 // 计算1 ~ 10000之间的累加和并打印返回 10 int sum = 0; 11 for (int i = 1; i <= 10000; i++) { 12 sum +=i; 13 } 14 System.out.println("计算的累加和是:" + sum); // 50005000 15 return sum; 16 }34 }
2. FutureTask类
<1> java.util.concurrent.FutureTask类:用于描述可取消的异步计算。该类提供了Future接口的基本实现,包括启动和取消计算、
查询计算是否完成以及检索计算结果的方法,也可以用于获取方法调用后的返回结果
<2> 常用方法
FutureTask(Callable callable) | 根据参数指定的引用,来创建一个未来任务 |
V get() | 获取call方法计算的结果 |
<3> 代码示例
1 import java.util.concurrent.Callable; 2 import java.util.concurrent.ExecutionException; 3 import java.util.concurrent.FutureTask; 4 5 public class ThreadCallableTest implements Callable { 6 7 @Override 8 public Object call() throws Exception { 9 // 计算1 ~ 10000之间的累加和并打印返回 10 int sum = 0; 11 for (int i = 1; i <= 10000; i++) { 12 sum +=i; 13 } 14 System.out.println("计算的累加和是:" + sum); // 50005000 15 return sum; 16 } 17 18 public static void main(String[] args) { 19 20 ThreadCallableTest tct = new ThreadCallableTest(); 21 FutureTask ft = new FutureTask(tct); 22 Thread t1 = new Thread(ft); 23 t1.start(); 24 Object obj = null; 25 try { 26 obj = ft.get(); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } catch (ExecutionException e) { 30 e.printStackTrace(); 31 } 32 System.out.println("线程处理方法的返回值是:" + obj); // 50005000 33 } 34 }
3. 线程池的由来
<1> 在服务器编程模型的原理:每一个客户端连接用一个单独的线程为之服务,当与客户端的会话结束时,线程也就结束了。
即,每来一个客户端连接,服务器端就要创建一个新线程
<2> 如果,访问服务器的客户端很多,那么,服务器要不断地创建和销毁线程,这将严重影响服务器地性能。
4. 线程池的概念和原理
<1> 概念:首先创建一些线程,它们的集合称为线程池。
当服务器接受到一个客户请求后,就从线程池中,取出一个空闲的线程,为之服务;
服务完后,不关闭该线程,而是将该线程还回到线程池中
<2> 原理:在线程池的编程模式下,任务是提交给整个线程池,而不是直接交给某个线程。
线程池在拿到任务后,它就在内部,找有无空闲的线程,再把任务交给内部某个空闲的线程。
任务是提交给整个线程池,一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务
5. 相关类和方法
<1> 从Java5开始,提供了线程池的相关类和接口: java.util.concurrent.Executors类 和 java.util.concurrent.ExecutorService接口
<2> Executors是个工具类和线程池的工厂类,可以创建并返回不同类型的线程池:
static ExecutorService newCachedThreadPool() | 创建一个可根据需要创建新线程的线程池 |
static ExecutorService newFixedThreadPool(int nThreads) | 创建一个可重用固定线程数的线程池 |
static ExecutorService newSingleThreadExecutor() | 创建一个只有一个线程的线程池 |
<3> ExecutorService接口是真正的线程池接口,主要实现类是 ThreadPoolExecutor,常用方法如下:
void execute(Runnable command) | 执行任务和命令,通常用于执行Runnable |
Future submit (Callable task) | 执行任务和命令,通常用于执行Callable |
void shutdown() | 启动有序关闭 |
<4> 代码示例
3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 6 public class ThreadPoolTest { 7 8 public static void main(String[] args) { 9 10 // 1.创建一个线程池 11 ExecutorService executorService = Executors.newFixedThreadPool(10); 12 // 2.向线程池中布置任务 13 executorService.submit(new ThreadCallableTest()); 14 // 3.关闭线程池 15 executorService.shutdown(); 16 } 17 }
6. 线程 - 练习