java 多线程 返回值_JAVA多线程实现和应用总结:如何使用有返回值的多线程
最近在做代码优化时学习和研究了下JAVA多线程的使用,看了菜鸟们的见解后做了下总结。
1.JAVA多线程实现方式
JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。
2.继承Thread类实现多线程继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread.run()");
}
}
在合适的地方启动线程如下:
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
3.实现Runnable接口方式实现多线程如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,如下:
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
事实上,当传入一个Runnable target参数给Thread后,Thread的run()方法就会调用target.run(),参考JDK源代码:
public void run() {
if (target != null) {
target.run();
}
}
4.使用ExecutorService、Callable、Future实现有返回结果的多线程
ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。想要详细了解Executor框架的可以访问http://www.javaeye.com/topic/366591,这里面对该框架做了很详细的解释。返回结果的线程是在JDK1.5中引入的新特征,确实很实用,有了这种特征我就不需要再为了得到返回值而大费周折了,而且即便实现了也可能漏洞百出。
可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。下面提供了一个完整的有返回结果的多线程测试例子,在JDK1.5下验证过没问题可以直接使用。代码如下:
import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
/**
* Java线程:有返回值的线程
*
* @author wb_qiuquan.ying
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
System.out.println("----程序开始运行----");
Date date1 = new Date();
int taskSize = 5;
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List list = new ArrayList();
for (int i = 0; i < taskSize; i++) {
Callable c = new MyCallable(i + " ");
// 执行任务并获取Future对象
Future f = pool.submit(c);
// System.out.println(">>>" + f.get().toString());
list.add(f);
}
// 关闭线程池
pool.shutdown();
// 获取所有并发任务的运行结果
for (Future f : list) {
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println(">>>" + f.get().toString());
}
Date date2 = new Date();
System.out.println("----程序结束运行----,程序运行时间【"
+ (date2.getTime() - date1.getTime()) + "毫秒】");
}
}
class MyCallable implements Callable {
private String taskNum;
MyCallable(String taskNum) {
this.taskNum = taskNum;
}
public Object call() throws Exception {
System.out.println(">>>" + taskNum + "任务启动");
Date dateTmp1 = new Date();
Thread.sleep(1000);
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>" + taskNum + "任务终止");
return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
}
}
代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
java 多线程 返回值_JAVA多线程实现和应用总结:如何使用有返回值的多线程相关推荐
- java null转空_Java对象为空时,将null转换为 保存值为空的属性
Java对象为空时,不显示该对象属性,或者将null转换为"" 第一种方法: @JsonInclude(JsonInclude.Include.NON_NULL) private ...
- java面试题解惑_JAVA面试题解惑系列(五)——传了值还是传了引用?
作者:臧圩人(zangweiren) 网址:http://zangweiren.javaeye.com >>>转载请注明出处! < < < JAVA中的传递都是值传 ...
- java获取map数量_java – 如何从HashMap或LinkedHashMap获取有限数量的值?
假设我有一个包含216个条目的LinkedHashMap,我如何从LinkedHashMap< Integer,Object>获取前100个值(此处为Object类型). 解决方法: 丑陋 ...
- java list键值_java基础之对List,Map,Set等集合键值对的简单认识
[一.集合] 特征: 数组:定长.可以放基本数据类型. List:变长.只能放对象.有序,可重复. Set :变长.只能放对象.无序,不可重复. Map :变长.只能放对象.无序,键值对. 重要实现类 ...
- java 字段为空设置默认值_java – 当字段为空时使用MyBatis添加默认值
当我的字段为空时,我想从数据库中插入默认值.我使用的是Oracle数据库. CREATE TABLE "EMPLOYEE" ("COL1" VARCHAR2(8 ...
- java 反射方法替换_Java在利用反射条件下替换英文字母中的值
Java在利用反射条件下替换英文字母中的值 (1)创建两个Class: ReflectTest类如下: package cn.itcast.day01; import java.lang.reflec ...
- java调用方法返回数组_JAVA使用下面的方法头编写方法,返回两个数组列表的并集...
importjava.util.Set;importjava.util.List;importjava.util.HashSet;importjava.util.TreeSet;importjava. ...
- java进程与线程_Java多线程笔记(零):进程、线程与通用概念
前言 不积跬步,无以至千里:不积小流,无以成江海.在学习Java多线程相关的知识前,我们首先需要去了解一点操作系统的进程.线程以及相关的基础概念. 进程 通常,我们把一个程序的执行称为一个进程.反过来 ...
- java main是多线程的吗_Java多线程之线程及其常用方法
创建线程和常用方法 进程与线程的概念进程 进程是程序执行时的一个实例.程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开 ...
最新文章
- Windows 7/Windows 8都有上帝模式
- Jenkins发布MVC应用程序
- linux下设备或资源忙,linux删除文件目录 目录设备或资源忙怎么办
- 编译原理——实验壹——TINY语言的词法分析
- 6-4-1:STL之list——list的快速入门、常用接口
- FastDFS学习总结(2)--Tracker与Storage配置详解
- if sql语句_SQL IF语句介绍和概述
- 智能媒体管理(IMM) Python SDK DEMO
- 答网友问:如何按月进行统计公司采购进货、销售出库信息?
- 数据-第18课-栈与递归
- C语言printf格式化输出
- PCIe扫盲——基于WinDriver快速开发PCIe驱动简明教程
- sudo rosdep init 出现 ERROR: cannot download default sources list from:
- Matlab guass-legendre求积代码
- 计算机设置了用户密码登录如何撤销6,台式电脑怎么设置和取消开机密码
- 计算机 取得高级权限,怎么获取电脑的最高管理员权限
- php 联合查询,多表联合查询
- cad快速选择命令快捷键_CAD快捷键命令:倒角的使用技巧
- 高通Q+A平台 android gcore解析环境搭建
- matlab某分子由25个原子组成,清华大学数学实验实验7无约束优化1
热门文章
- PAT 7-1 厘米换算英尺英寸
- 【WPF学习】第五十四章 关键帧动画
- linux学习(超全)
- 工业相机的传输接口作用以及区别分析
- C语言用头插法建立单链表
- Xmind 思维导图v22
- php项目的流程图怎么画,工作中的项目流程图怎么画
- Solver lbfgs supports only “l2” or “none” penalties, got l1 penalty.解决办法
- echarts 日历热度图设置 calendar
- Sql Server中and和or的优先级问题