Java多线程(七)新增创建线程的方式

新增方式一:实现Callable接口

与使用Runnable相比, Callable功能更强大些
  • 相比run()方法,可以有返回值
  • 方法可以抛出异常
  • 支持泛型的返回值
  • 需要借助FutureTask类,比如获取返回结果
Future接口
  • 可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。
  • FutrueTask是Futrue接口的唯一的实现类
  • FutureTask 同时实现了Runnable, Future接口。它既可以作为
  • Runnable被线程执行,又可以作为Future得到Callable的返回值
 1 /**
 2  * 创建线程的方式三:实现Callable接口。 --- JDK 5.0新增
 3  *
 4  *
 5  * 如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
 6  * 1. call()可以有返回值的。
 7  * 2. call()可以抛出异常,被外面的操作捕获,获取异常的信息
 8  * 3. Callable是支持泛型的
 9 
10  */
11 //1.创建一个实现Callable的实现类
12 class NumThread implements Callable{
13     //2.实现call方法,将此线程需要执行的操作声明在call()中
14     @Override
15     public Object call() throws Exception {
16         int sum = 0;
17         for (int i = 1; i <= 100; i++) {
18             if(i % 2 == 0){
19                 System.out.println(i);
20                 sum += i;
21             }
22         }
23         return sum;
24     }
25 }
26 
27 
28 public class ThreadNew {
29     public static void main(String[] args) {
30         //3.创建Callable接口实现类的对象
31         NumThread numThread = new NumThread();
32         //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象
33         FutureTask futureTask = new FutureTask(numThread);
34         //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
35         new Thread(futureTask).start();
36 
37         try {
38             //6.获取Callable中call方法的返回值
39             //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
40             Object sum = futureTask.get();
41             System.out.println("总和为:" + sum);
42         } catch (InterruptedException e) {
43             e.printStackTrace();
44         } catch (ExecutionException e) {
45             e.printStackTrace();
46         }
47     }
48 }

新增方式二:使用线程池

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。
好处
  • 提高响应速度(减少了创建新线程的时间)
  • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
  • 便于线程管理

    corePoolSize:核心池的大小

    maximumPoolSize:最大线程数

    keepAliveTime:线程没有任务时最多保持多长时间后会终止

线程池相关API

JDK 5.0起提供了线程池相关API:ExecutorService 和 Executors
ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行Runnable
<T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般又来执行Callable
void shutdown() :关闭连接池
Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池
 Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池
 Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池
 Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池
 Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
 1 import java.util.concurrent.ExecutorService;
 2 import java.util.concurrent.Executors;
 3 import java.util.concurrent.ThreadPoolExecutor;
 4 
 5 /**
 6  * 创建线程的方式四:使用线程池
 7  *
 8  * 好处:
 9  * 1.提高响应速度(减少了创建新线程的时间)
10  * 2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
11  * 3.便于线程管理
12  *      corePoolSize:核心池的大小
13  *      maximumPoolSize:最大线程数
14  *      keepAliveTime:线程没有任务时最多保持多长时间后会终止
15  *
16  *
17  * 面试题:创建多线程有几种方式?四种!
18  */
19 
20 class NumberThread implements Runnable{
21 
22     @Override
23     public void run() {
24         for(int i = 0;i <= 100;i++){
25             if(i % 2 == 0){
26                 System.out.println(Thread.currentThread().getName() + ": " + i);
27             }
28         }
29     }
30 }
31 
32 class NumberThread1 implements Runnable{
33 
34     @Override
35     public void run() {
36         for(int i = 0;i <= 100;i++){
37             if(i % 2 != 0){
38                 System.out.println(Thread.currentThread().getName() + ": " + i);
39             }
40         }
41     }
42 }
43 
44 public class ThreadPool {
45 
46     public static void main(String[] args) {
47         //1. 提供指定线程数量的线程池
48         ExecutorService service = Executors.newFixedThreadPool(10);
49         ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
50         //设置线程池的属性
51 //        System.out.println(service.getClass());
52 //        service1.setCorePoolSize(15);
53 //        service1.setKeepAliveTime();
54 
55 
56         //2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象
57         service.execute(new NumberThread());//适合适用于Runnable
58         service.execute(new NumberThread1());//适合适用于Runnable
59 
60 //        service.submit(Callable callable);//适合使用于Callable
61         //3.关闭连接池
62         service.shutdown();
63     }
64 
65 }

 

posted @ 2021-07-10 16:33  雪之下。  阅读(282)  评论(0)    收藏  举报