java 给某个类创建线程_Java 多线程 之 创建线程的另外两种方式(JDK5.0新增)

一、创建线程新增方式一:实现 Callable 接口

1、Callable概述

与使用 Runnable 相比,Callable 功能更强大些

① 相比 run() 方法,可以有返回值;

② 方法可以抛出异常;

③ 支持泛型的返回值;

④ 需要借助 FutureTask 类,比如获取返回结果;

2、Future接口

(1)可以对具体 Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等;

(2)FutureTask 是 Future 接口的唯一的实现类;

(3)FutureTask 同时实现了 Runnable,Future 接口。它既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值;

3、使用步骤

(1)创建一个实现Callable的实现类;

(2)实现call方法,将此线程需要执行的操作声明在call()中;

(3)创建Callable接口实现类的对象;

(4)将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象;

(5)将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()

4、代码示例

1 public classThreadNew {2 public static voidmain(String[] args) {3 //3.创建Callable接口实现类的对象

4 NumberThread numberThread = newNumberThread();5

6 //4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象

7 FutureTask futureTask = new FutureTask<>(numberThread);8

9 //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()

10 newThread(futureTask).start();11

12

13 try{14 //6.获取Callable中call方法的返回值15

16 //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。

17 Object sum =futureTask.get();18 System.out.println("总和为:" +sum);19 } catch(InterruptedException e) {20 e.printStackTrace();21 } catch(ExecutionException e) {22 e.printStackTrace();23 }24 }25 }26

27 //1.创建一个实现Callable的实现类

28 class NumberThread implementsCallable {29 //2.实现call方法,将此线程需要执行的操作声明在call()中

30 @Override31 public Object call() throwsException {32 int sum = 0;33 for (int i = 0; i <= 100; i++) {34 if (i % 2 == 0) {35 System.out.println(i);36 sum +=i;37 }38 }39 returnsum;40 }41 }

二、创建线程:使用线程池

1、线程池思想概述

如果使用线程的时候就去创建一个线程,这样实现起来非常简便,但是会出现一个问题:

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

Java 中可以通过线程池使线程可以复用,就是执行完一个任务,并不是销毁,还可以继续执行其他的任务。

2、线程池概念

线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复利用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。

线程池中很多操作都是优化资源相关的,下面通过图来了解线程池的工作原理:

967543216b70ee3140fb82ec7434f13c.png

cd24825fae06260058030b5caa27bf88.bmp

3、线程池好处

(1) 降低资源消耗,减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务;

(2)提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行;

(3)提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机 )

三、线程池的使用

1、概述

JDK1.5 之后,java 里面线程池的顶级接口是 java.util.concurrent.Executor,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 java.util.concurrent.ExecutorService。

JDK 5.0起提供了线程池相关API: ExecutorService 和 Executors。

2、ExecutorService

ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor

void execute(Runnable command) :执行任务/命令,没有返回值,一般用来执行Runnable

Future submit(Callable task):执行任务,有返回值,一般又来执行Callable,获取线程池中的某一个线程对象,并执行;Future 接口:用来记录线程任务执行完毕后产生的结果,线程池创建与使用

void shutdown() :关闭/销毁连接池的方法

3、Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池

要配置一个线程池是比较复杂的,因此 java.util.concurrent.Excutors 线程工厂里面提供了一些静态方法,生成一些常用的线程池。

Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池

Executors.newFixedThreadPool(n); 创建一个可重用固定线程数的线程池

Executors.newSingleThreadExecutor() :创建一个只有一个线程的线程池

Executors.newScheduledThreadPool(n):创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

返回值:ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)

4、ThreadPoolExecutor

ThreadPoolExecutor 是ExecutorService的具体子类,通过此类我们进行线程池的一些常用设置:

corePoolSize:核心池的大小

maximumPoolSize:最大线程数

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

5、使用线程池中的步骤

① 使用线程池的工厂类Executors里边提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池

② 创建一个类,实现Runnable接口,重写run方法,设置线程任务

③ 调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法

④ 调用ExecutorService中的方法shutdown销毁线程池(不建议执行)

四、代码示例

1、示例一

1 public classThreadPool {2 public static voidmain(String[] args) {3 //1. 提供指定线程数量的线程池

4 ExecutorService service = Executors.newFixedThreadPool(10);5 ThreadPoolExecutor service1 =(ThreadPoolExecutor) service;6 //设置线程池的属性7 //System.out.println(service.getClass());8 //service1.setCorePoolSize(15);9 //service1.setKeepAliveTime();10

11

12 //2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象

13 service.execute(new NumThread());//适合适用于Runnable

14 service.execute(new NumThread1());//适合适用于Runnable15

16 //service.submit(Callable callable);//适合使用于Callable17 //3.关闭连接池

18 service.shutdown();19 }20 }21 class NumThread implementsRunnable{22

23 @Override24 public voidrun() {25 for(int i = 0;i <= 100;i++){26 if(i % 2 == 0){27 System.out.println(Thread.currentThread().getName() + ": " +i);28 }29 }30 }31 }32

33 class NumThread1 implementsRunnable{34

35 @Override36 public voidrun() {37 for(int i = 0;i <= 100;i++){38 if(i % 2 != 0){39 System.out.println(Thread.currentThread().getName() + ": " +i);40 }41 }42 }43 }

2、示例二

1 public classThreadPool1 {2 public static voidmain(String[] args) {3 //1.使用线程池的工厂类Executors里边提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池

4 ExecutorService es = Executors.newFixedThreadPool(10);5 //3.调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法

6 es.submit(new RunnableImpl());//pool-1-thread-1创建了一个新的线程执行7 //注意:线程池会一直开启,使用完了线程,会自动把线程归还给线程池,线程可以继续使用

8 es.submit(new RunnableImpl());//pool-1-thread-1创建了一个新的线程执行

9 es.submit(new RunnableImpl());//pool-1-thread-2创建了一个新的线程执行10

11 //4.调用ExecutorService中的方法shutdown销毁线程池(不建议执行)

12 es.shutdown();13

14 es.submit(new RunnableImpl());//抛异常,线程池都没有了,就不能获取线程了

15 }16 }17

18

19 //2. 实现 Runnable 创建线程类

20 class RunnableImpl implementsRunnable {21 @Override22 public voidrun() {23 System.out.println(Thread.currentThread().getName() + "创建了一个新的线程执行");24 }25 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值