前言:
虽然 java 的 API 中说创建多线程的方式只有两种 (There are two ways to create a new thread of execution), 分别是继承 Thread 类创建和实现 Runnable 接口创建, 在上一篇博文中演示了这两种, 详见 https://www.cnblogs.com/coding-996/p/12104570.html , 但是 JDK5.0 以后新增了两种, 分别是实现 Callable 接口创建和使用线程池创建, 本次就演示后两种创建方式并分析其特性.
实现 Runnable 接口创建多线程
创建步骤:
1. 创建一个实现 Callable 接口的类.
2. 重写 call() 方法, 线程需要执行的代码都放到 call 方法中.
3. 创建实现 Callable 接口类的实例对象.
4. 将步骤 3 的对象作为参数传给 FutureTask 构造器中, 创建 FutureTask 对象.
5. 将 FutureTask 的对象作为参数传给 Thread 类, 创建对象并调用 start() 方法.
- package day02;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.FutureTask;
- // 创建一个多线程, 输出 20 以内的偶数, 并返回所有偶数的和
- //1. 创建一个实现 `Callable` 接口的类.
- class TestSum implements Callable{
- //2. 重写 call() 方法, 线程需要执行的代码都放到 call 方法中.
- @Override
- public Object call() throws Exception{
- int sum = 0;
- for(int i = 1;i <= 20 ;i++ ){
- if(i % 2 == 0){
- System.out.println(i);
- sum = sum + i;
- }
- }
- return sum;
- }
- }
- public class ThreadCall {
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- //3. 创建实现 `Callable` 接口类的实例对象.
- TestSum test = new TestSum();
- //4. 将步骤 3 的对象作为参数传给 `FutureTask` 构造器中, 创建 `FutureTask` 对象.
- FutureTask futuretask = new FutureTask(test);
- //5. 将 `FutureTask` 的对象作为参数传给 `Thread` 类, 创建对象并调用 start() 方法.
- Thread thread = new Thread(futuretask);
- thread.start();
- //get 方法可以获取返回值
- System.out.println("偶数总合是:"+futuretask.get());
- }
- }
- // 输出结果:
- 2
- 4
- 6
- 8
- 10
- 12
- 14
- 16
- 18
- 20
偶数总合是: 110
实现 Callable 接口创建多线程的特点:
? 1.call() 方法可以有返回值, 可以使用 get() 方法获取返回值.
? 2.call() 方法可以抛出异常, 而且能被外面捕获到.
? 3.Callable 支持泛型.
使用线程池创建多线程
一. 实现 Runnable 接口的方式创建:
- package day02;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- class Number implements Runnable{
- @Override
- public void run() {
- for (int i = 0; i < 20; i++) {
- if (i % 2 == 0){
- System.out.println(Thread.currentThread().getName()+":"+i);
- }
- }
- }
- }
- public class ThreadPool {
- public static void main(String[] args){
- ExecutorService service = Executors.newFixedThreadPool(10);
- Number num = new Number();
- service.execute(num);
- service.shutdown();
二. 实现 Callable 接口的方式创建:
- package day02;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- class Number implements Callable {
- @Override
- public Object call() {
- for (int i = 0; i < 20; i++) {
- if (i % 2 == 0){
- System.out.println(Thread.currentThread().getName()+":"+i);
- }
- }
- return null;
- }
- }
- public class ThreadPool {
- public static void main(String[] args){
- ExecutorService service = Executors.newFixedThreadPool(10);
- Number num = new Number();
- service.submit(num);// 区别在这里
- service.shutdown();
- }
- }
线程池好处:
1. 频繁创建线程和销毁使用量较大的资源, 比如并发的线程, 对性能影响较大, 所以需要创建线 程池存放线程, 使用的时候直接获取, 实现重复利用, 提高效率.
2. 降低创建线程时间, 提高响应速度.
3. 降低资源的消耗.
4. 便于线程管理.
来源: http://www.bubuko.com/infodetail-3365520.html