最近在做代码优化时学习和研究了下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多线程实现和应用总结:如何使用有返回值的多线程相关推荐

  1. java null转空_Java对象为空时,将null转换为 保存值为空的属性

    Java对象为空时,不显示该对象属性,或者将null转换为"" 第一种方法: @JsonInclude(JsonInclude.Include.NON_NULL) private ...

  2. java面试题解惑_JAVA面试题解惑系列(五)——传了值还是传了引用?

    作者:臧圩人(zangweiren) 网址:http://zangweiren.javaeye.com >>>转载请注明出处! < < < JAVA中的传递都是值传 ...

  3. java获取map数量_java – 如何从HashMap或LinkedHashMap获取有限数量的值?

    假设我有一个包含216个条目的LinkedHashMap,我如何从LinkedHashMap< Integer,Object>获取前100个值(此处为Object类型). 解决方法: 丑陋 ...

  4. java list键值_java基础之对List,Map,Set等集合键值对的简单认识

    [一.集合] 特征: 数组:定长.可以放基本数据类型. List:变长.只能放对象.有序,可重复. Set :变长.只能放对象.无序,不可重复. Map :变长.只能放对象.无序,键值对. 重要实现类 ...

  5. java 字段为空设置默认值_java – 当字段为空时使用MyBatis添加默认值

    当我的字段为空时,我想从数据库中插入默认值.我使用的是Oracle数据库. CREATE TABLE "EMPLOYEE" ("COL1" VARCHAR2(8 ...

  6. java 反射方法替换_Java在利用反射条件下替换英文字母中的值

    Java在利用反射条件下替换英文字母中的值 (1)创建两个Class: ReflectTest类如下: package cn.itcast.day01; import java.lang.reflec ...

  7. java调用方法返回数组_JAVA使用下面的方法头编写方法,返回两个数组列表的并集...

    importjava.util.Set;importjava.util.List;importjava.util.HashSet;importjava.util.TreeSet;importjava. ...

  8. java进程与线程_Java多线程笔记(零):进程、线程与通用概念

    前言 不积跬步,无以至千里:不积小流,无以成江海.在学习Java多线程相关的知识前,我们首先需要去了解一点操作系统的进程.线程以及相关的基础概念. 进程 通常,我们把一个程序的执行称为一个进程.反过来 ...

  9. java main是多线程的吗_Java多线程之线程及其常用方法

    创建线程和常用方法 进程与线程的概念进程 进程是程序执行时的一个实例.程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开 ...

最新文章

  1. Windows 7/Windows 8都有上帝模式
  2. Jenkins发布MVC应用程序
  3. linux下设备或资源忙,linux删除文件目录 目录设备或资源忙怎么办
  4. 编译原理——实验壹——TINY语言的词法分析
  5. 6-4-1:STL之list——list的快速入门、常用接口
  6. FastDFS学习总结(2)--Tracker与Storage配置详解
  7. if sql语句_SQL IF语句介绍和概述
  8. 智能媒体管理(IMM) Python SDK DEMO
  9. 答网友问:如何按月进行统计公司采购进货、销售出库信息?
  10. 数据-第18课-栈与递归
  11. C语言printf格式化输出
  12. PCIe扫盲——基于WinDriver快速开发PCIe驱动简明教程
  13. sudo rosdep init 出现 ERROR: cannot download default sources list from:
  14. Matlab guass-legendre求积代码
  15. 计算机设置了用户密码登录如何撤销6,台式电脑怎么设置和取消开机密码
  16. 计算机 取得高级权限,怎么获取电脑的最高管理员权限
  17. php 联合查询,多表联合查询
  18. cad快速选择命令快捷键_CAD快捷键命令:倒角的使用技巧
  19. 高通Q+A平台 android gcore解析环境搭建
  20. matlab某分子由25个原子组成,清华大学数学实验实验7无约束优化1

热门文章

  1. PAT 7-1 厘米换算英尺英寸
  2. 【WPF学习】第五十四章 关键帧动画
  3. linux学习(超全)
  4. 工业相机的传输接口作用以及区别分析
  5. C语言用头插法建立单链表
  6. Xmind 思维导图v22
  7. php项目的流程图怎么画,工作中的项目流程图怎么画
  8. Solver lbfgs supports only “l2” or “none” penalties, got l1 penalty.解决办法
  9. echarts 日历热度图设置 calendar
  10. Sql Server中and和or的优先级问题