今天简单说一下Java三种多线程实现方式和区别,主要有实现Runnable、Callable和继承Thread三种方式。

实现Runnable的方式

这种方式比较常用,当我们的线程类有继承其他的类的情况下(Java不支持类多继承),并且线程任务不需要返回值的情况下可以选用这种方式。

public class ThreadRunnableDemo implementsRunnable{

/**计数变量*/

private int count = 0;

public static void main(String[] args) throwsInterruptedException {

ThreadRunnableDemo threadRunnableDemo = newThreadRunnableDemo();

//实例化线程

Thread thread = new Thread(threadRunnableDemo, "threadRunnableDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));

//启动线程

thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));

//主线程休眠1000ms

Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", thread.getState()));

}

@Override public voidrun() {

count++;

System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count));

} }

输出结果:

线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadRunnableDemoA, 线程状态:RUNNABLE, count:1

线程状态after1000ms: TERMINATED

实现Callable的方式

当我们执行线程需要返回值的时候那么就必须选用实现Callable类的方式,因为目前只有这种方式能返回值。当然这种方式我们也可以不需要获取返回值。

这种方式是通过FutureTask的get()方法(下面代码的第22行)或者get(long timeout, TimeUnit unit)(下面代码的第28行)方法获取返回值。当我们看Callable的接口定义的源码会发现“public interface Callable ” ,我们实现的时候是需要定义返回类型,如下面代码所示。

除此之外我们还需要注意的是:当我们通过FutureTask的get()方法去获取线程的返回值的时候是要等到线程call()内容都执行完毕之后才能获取得到,并且get()方法后面的代码必须等待,说明这一定是同步的,所以我们可以在真正需要线程返回值的时候才通过get()方法去获取,以免被阻塞。当我们通过get(long timeout, TimeUnit unit)方式去获取的时候可以设置超时时间,如果超过所设置的超时时间都没有获取到线程返回的值则会抛出 java.util.concurrent.TimeoutException 异常,当然如果在get(long timeout, TimeUnit unit)之前用get()方式获取了的话就不会抛异常。

实现Callable还有个好处就是可以线程可以抛异常,如果我们需要在线程里抛出异常的话也可以选用这种方式,其他两种方式只能捕获异常信息。

public class ThreadCallableDemo implements Callable{

/**计数变量*/

private int count = 0;

public static void main(String[] args) throwsInterruptedException, ExecutionException, TimeoutException {

ThreadCallableDemo threadCallableDemo = newThreadCallableDemo();

//通过FutureTask获取返回值

FutureTask taskA = new FutureTask<>(threadCallableDemo);

//实例化线程

Thread thread = new Thread(taskA, "threadCallableDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));

//启动线程

thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));

//通过FutureTask的get()方法获取返回值

int result =taskA.get(); System.out.println("是否同步测试...."); System.out.println(String.format("result: %s", result)); System.out.println(String.format("线程状态afterGetResult1: %s", thread.getState()));

//通过FutureTask的get()方法获取返回值 设置超时时间 单位为ms

int resultWithTime = taskA.get(100, TimeUnit.MILLISECONDS); System.out.println(String.format("resultWithTime: %s", resultWithTime)); System.out.println(String.format("线程状态afterGetResult2: %s", thread.getState()));

}

/**

* 实现Callable的call类 */

@Override public Integer call() throwsException {

//自增

count++;

System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); System.out.println("休眠1000ms...."); Thread.currentThread().sleep(1000);

returncount; } }

输出结果:

线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadCallableDemoA, 线程状态:RUNNABLE, count:1

休眠1000ms.... 是否同步测试.... result: 1

线程状态afterGetResult1: TERMINATED resultWithTime: 1

线程状态afterGetResult2: TERMINATED

继承Thread的方式

Thread类实际上也是实现Runnable接口,所以当我们继承Thread的时候我们即使不实现run()方法也不会报错,这种方式也经常用。

下面我写了两种不同继承Thread的代码,大家可以看一下区别,我在网上看到很多人说 继承Thread实现多线程,线程间不能共享数据,但是我用下面的代码1方式似乎也可以共享哇,欢迎大家提出质疑。

代码1:

public class ThreadThreadDemo extendsThread{

/**计数变量*/

private int count = 0;

public static void main(String[] args) throwsInterruptedException {

ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();

//实例化线程

Thread thread = new Thread(threadThreadDemo, "threadThreadDemoA"); System.out.println(String.format("线程状态preStart: %s", thread.getState()));

//启动线程

thread.start(); System.out.println(String.format("线程状态afterStart: %s", thread.getState()));

//主线程休眠1000s

Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", thread.getState())); }

@Override public voidrun() {

count++;

System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }

输出结果1:

线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:threadThreadDemoA, 线程状态:RUNNABLE, count:1

线程状态after1000ms: TERMINATED

代码2:

public class ThreadThreadDemo extendsThread{

/**计数变量*/

private int count = 0;

public static void main(String[] args) throwsInterruptedException {

ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();

//实例化线程

System.out.println(String.format("线程状态preStart: %s", threadThreadDemo.getState()));

//启动线程

threadThreadDemo.start(); System.out.println(String.format("线程状态afterStart: %s", threadThreadDemo.getState()));

//主线程休眠1000s

Thread.sleep(1000); System.out.println(String.format("线程状态after1000ms: %s", threadThreadDemo.getState())); }

@Override public voidrun() {

count++;

System.out.println(String.format("线程名称:%s, 线程状态:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }

输出结果2:

线程状态preStart: NEW 线程状态afterStart: RUNNABLE 线程名称:Thread-0, 线程状态:RUNNABLE, count:1

线程状态after1000ms: TERMINATED

最后总结:

如果不要求线程返回结果,也不需要抛异常也没有继承其他的类,那么三种方式可以任选,看喜好;

如果有继承其他类,那么就只能用实现Runnable和实现Callable的方式;

如果需要线程返回结果或者需要线程抛异常那么选择实现Callable的方式的方式,但是需要注意的是获取返回结果是同步的方式。

如果有疑问或者有问题欢迎留言讨论!

java多线程实现表复制_Java多线程的三种实现方式相关推荐

  1. java如何实现定时任务_Java定时任务的三种实现方式

    前言 现代的应用程序早已不是以前的那些由简单的增删改查拼凑而成的程序了,高复杂性早已是标配,而任务的定时调度与执行也是对程序的基本要求了. 很多业务需求的实现都离不开定时任务,例如,每月一号,移动将清 ...

  2. java中有scoreframe类型嘛_java构造函数的三种类型总结

    我们说构造函数能处理参数的问题,但其实也要分三种情况进行讨论.目前有三种类型:无参.有参和默认.根据不同的参数情况,需要我们分别进行构造函数的讨论.这里重点是无参构造函数的初始化也要分两种方法进行分析 ...

  3. java数组初始化赋值_Java数组的三种初始化方式

    Java语言中数组必须先初始化,然后才可以使用.所谓初始化就是为数组的数组元素分配内存空间,并为每个数组元素附初始值. 注意:数组完成初始化后,内存空间中针对该数组的各个元素就有个一个默认值: 基本数 ...

  4. java 工厂模式的写法_java工厂模式三种详解

    工厂方法模式(Factory Method) 工厂方法模式分为三种: 1.普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.首先看下关系图: 举例如下:(我们举一个发送邮件和短 ...

  5. Java中用户向系统传递参数的三种基本方式

    使用Main方法的参数传递方式 例示代码如下: [java] view plaincopy public class MainArgs { public static void main(String ...

  6. Java中String转换为单字String集合的三种实现方式

    最近一次编程中,需要将String对象转换为单个字符的String的集合.刚开始以为有String有现成的方法,后来没有找到,所以还是要自己写.也许是这个需求太另类了吧.以下是我先后实现的三种方式. ...

  7. Java多线程的三种实现方式(重点看Collable接口实现方式)

    1.通过继承Thread类来实现多线程 在继承Thread类之后,一定要重写类的run方法,在run方法中的就是线程执行体,在run方法中,直接使用this可以获取当前线程,直接调用getName() ...

  8. Java多线程:多线程同步安全问题的 “三“ 种处理方式 ||多线程 ”死锁“ 的避免 || 单例模式”懒汉式“的线程同步安全问题

    Java多线程:多线程同步安全问题的 "三" 种处理方式 ||多线程 "死锁" 的避免 || 单例模式"懒汉式"的线程同步安全问题 每博一文 ...

  9. java中map的遍历方法_Java中Map的三种遍历方式

    集合中的三种遍历方式,如下代码: import java.util.Collection; import java.util.HashMap; import java.util.Iterator; i ...

最新文章

  1. android pjsip 2.5编译,在Android中构建PJSiP时出错
  2. 拒绝加班,办公电脑换新低至¥1999
  3. oracle 监听服务自动停止与无法启动问题
  4. cocos2d-x jsbinding 在线更新策略设计
  5. python表白程序-python如何写出表白程序
  6. Leetcode 153. 寻找旋转排序数组中的最小值 解题思路及C++实现
  7. Swift类扩展使用方法
  8. Redis双机热备方案--转
  9. mysql 主从同步 工具_mysql主从同步工具maatkit安装
  10. 基于matlab的频域辨识,基于Lab VIEW的控制系统频域分析研究
  11. 辽源天气预报软件测试,辽源天气预报15天
  12. HDU 3951 (博弈) Coin Game
  13. python怎样查看describe的结果_Python学习第126课--pandas拿到数据后的总体描述
  14. python module错误_python 解决方法:ImportError: No module
  15. java仓库管理设计报告_基于javaweb的仓库管理系统的设计和实现 毕业论文
  16. WEB开发技术 知识点总结
  17. win10+VS2017+DX11踩的那些雷
  18. cesium接入加载3D城市建筑物(离线)(cesium篇.19)
  19. 错误代码warning C4013: ‘sqrt‘ undefined; assuming extern returning int怎么解决?
  20. “我的恩典是够你用的”(哥林多后书十二章9节)

热门文章

  1. 如何更改java源码_java – 如何在Android中更改ImageView源码
  2. 生产者跟消费者问题(C++实现)
  3. 高斯--塞德尔迭代法求方程组的解(Python实现)
  4. [简单题]换一个思维,代码简洁度就完全变了(Python实现)
  5. Visdom数据可视化工具绘制Loss曲线
  6. 计算器的程序代码java_java 简单的计算器程序实例代码
  7. CF438E The Child and Binary Tree 生成函数、多项式开根
  8. Laravel源码解析之从入口开始
  9. Linux手动分区步骤
  10. Selector-背景选择器