实现Callable接口创建线程

Callable接口是在jdk5版本中加入的,这个接口在java.util.concurrent包下面,与其他两种方式不同的地方在于使用Callable接口创建的线程会获得一个返回值并且可以声明异常。

使用Callable创建线程步骤:

1.自定义一个类实现java.util.concurrent包下的Callable接口
2.重写call方法
3.将要在线程中执行的代码编写在call方法中
4.创建ExecutorService线程池
5.将自定义类的对象放入线程池里面
6.获取线程的返回结果
7.关闭线程池,不再接收新的线程,未执行完的线程不会被关闭
package com.sutaoyu.Thread;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; class MyCallable implements Callable<Integer>{
//睡眠时间
private long second; //计算阶乘
private int count; public MyCallable(int count, long second) {
this.count = count;
this.second = second;
} //重写call方法
@Override
public Integer call() throws Exception {
// 3.将要执行的代码写在call方法中
// 计算阶乘
//让当前线程睡眠,单位是毫秒 Thread.sleep(second);
int sum = 1;
if(count == 0) {
sum = 0;
}else {
for(int i = 1;i <= count;i++) {
sum *= 1;
}
} //打印线程名称
System.out.println(Thread.currentThread().getName() + "--------sum=" + sum); return sum;
}
public int getCount() {
return count;
} public void setCount(int count) {
this.count = count;
}
} public class test_3 { public static void main(String[] args) throws InterruptedException, ExecutionException {
//4.创建ExecutorService线程池
ExecutorService exec = Executors.newCachedThreadPool(); //5.创建存储Future对象的集合,用来存放ExecutorService的执行结果
ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(); //6.开启2个线程,将返回的Future对象放入集合中
for(int i = 0;i < 2;i++) {
if(i == 0) {
//计算5的阶乘,睡眠10秒
results.add(exec.submit(new MyCallable(5, 10000)));
}else {
//计算3的阶乘,睡眠i秒
results.add(exec.submit(new MyCallable(3, i)));
}
}
for (Future<Integer> fs : results) {
//7.判断线程是否执行结束,如果执行结束就将结果打印
if (fs.isDone()) {
System.out.println("计算结果:" + fs.get());
} else {
System.out.println(fs.toString() + "该线程还没有计算完毕,请耐心等待");
}
} //8.关闭线程池,不再接收新的线程,未执行完的线程不会被关闭
exec.shutdown();
System.out.println("main方法执行结束");
}
}

线程池

线程池是初始化一个多线程应用程序过程中创建一个线程集合,然后在需要执行新的任务时直接去这个线程集合中获取,而不是创建一个线程。任务执行结束后,线程回到池子中等待下一次的分配。

线程池的作用
解决创建单个线程耗费时间和资源的问题。

创建线程池
上面代码中演示了两种方式创建线程池

    • Executors.newFixedThreadPool(int nThreads);
      通过传入的int类型参数来指定创建线程池中的线程数,如果任务6666666666666数量大于线程数量,则任务会进行等待。
    • Executors.newCachedThreadPool();
      会根据需要创建新线程的线程池,如果线程池中的线程数量小于任务数时,会创建新的线程,线程池中的线程最大数量是Integer.MAX_VALUE,int类型的最大值。如果线程的处理速度小于任务的提交速度时,会不断创建新的线程来执行任务,这样有可能会因为创建过多线程而耗尽CPU 和内存资源。

51、多线程创建的三种方式之实现Callable接口的更多相关文章

  1. 50、多线程创建的三种方式之实现Runnable接口

    实现Runnable接口创建线程 使用Runnable创建线程步骤: package com.sutaoyu.Thread; //1.自定义一个类实现java.lang包下的Runnable接口 cl ...

  2. 49、多线程创建的三种方式之继承Thread类

    继承Thread类创建线程 在java里面,开发者可以创建线程,这样在程序执行过程中,如果CPU空闲了,就会执行线程中的内容. 使用Thread创建线程的步骤: 1.自定义一个类,继承java.lan ...

  3. 如何实现有返回值的多线程 JAVA多线程实现的三种方式

    可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口.执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable ...

  4. 于Unity3D动态创建对象和创建Prefab三种方式的原型对象

    于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...

  5. 黑马vue---56-58、vue组件创建的三种方式

    黑马vue---56-58.vue组件创建的三种方式 一.总结 一句话总结: 不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素 1.使用 Vu ...

  6. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  7. Java中 实现多线程成的三种方式(继承,实现,匿名内部类)

    ---------------------------------------------------------------------------------------------------- ...

  8. JAVA多线程实现的三种方式

    JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  9. SpringBoot工程创建的三种方式

    一. 通过IDEA的spring Initializer创建 1. 打开创建项目面板 File->New->Project->Spring Initializr 2. 填写Maven ...

随机推荐

  1. 微信小程序 功能函数 密码验证*

    //登录输入密码 userPasswordInput: function (e) { var that = this; this.setData({ userPassword: e.detail.va ...

  2. response和request的setCharacterEncoding区别

    一.request.setCharacterEncoding():是设置从request中取得的值或从数据库中取出的值. 指定后可以通过getParameter()则直接获得正确的字符串,如果不指定, ...

  3. Delphi : keydown与keypress的区别,组合键

    Shift 是一个集合变量. type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDoubl ...

  4. UVAlive3523_Knights of the Round Table

    圆桌骑士.有的骑士之间是相互憎恨的,不能连坐,需要安排奇数个骑士围着桌子坐着,大于3个,求哪些骑士不可能安排到座位. 根据给定的关系,如果两个骑士之间没有憎恨关系,那么连边.最终就是求有多少个点无法位 ...

  5. NewSQL 介绍

    1.CAP: CAP原理:• Consistency(一致性): 数据一致更新,所有数据变动都是同步的• Availability(可用性): 好的响应性能• Partition tolerance( ...

  6. API接口测试中需要注意的地方

    1.检查接口返回的数据是否与预期结果一致. 2.检查接口的容错性,假如传递数据的类型错误时是否可以处理.例如是支持整数,传递的是小数或字符串呢? 3.接口参数的边界值.例如,传递的参数足够大或为负数时 ...

  7. Finding LCM LightOJ - 1215 (水题)

    这题和这题一样......只不过多了个数... Finding LCM LightOJ - 1215 https://www.cnblogs.com/WTSRUVF/p/9316412.html #i ...

  8. shiro异常类型

    <!-- 身份认证异常 --> <!-- 身份令牌异常,不支持的身份令牌 --> org.apache.shiro.authc.pam.UnsupportedTokenExce ...

  9. 页面: Fork me on GitHub

    一.实现效果如下: 二.代码地址:https://github.com/blog/273-github-ribbons 这是一个国外网友开发的代码, 里面有很多种样式,可以自已随心选择. 三.我们只拿 ...

  10. number类型转化为string类型

    toString 方法 string = toString(num) 缺点: 不能转化 underfind 和 null 2 String 方法 string = String(num) 可以转化 u ...