1. 继承Thread类来实现

class MyThread extends Thread{
@Override
public void run() {
System.out.println("myThread is running");
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
 

  由于在java中采用单继承的模式,因此继承Thread类有一个明显的缺点就是占用了唯一的extends,是的我们无法在继承其它的类,因此一般不会采用这种方式。

2. 实现Runnable接口

 

class MyRun implements Runnable{

    @Override
public void run() {
System.out.println("myThread is running");
}
}
public static void main(String[] args) {
// MyThread thread = new MyThread();
// thread.start(); Thread thread1 = new Thread(new MyRun());
thread1.start();
}

  我们通过Runnable接口来实现线程实际上是策略模式的实现(策略模式可以参考我之前写的博客)。我们通过实现 run()来实现自己要完成的事情。

3. 通过Callable来实现可返回值的线程

class MyCallable implements Callable{   //实现接口Callable

    @Override
public Object call() throws Exception {
return "my callable is running";
}
}
  public static void main(String[] args) throws ExecutionException, InterruptedException {
// MyThread thread = new MyThread();
// thread.start(); // Thread thread1 = new Thread(new MyRun());
// thread1.start(); FutureTask task = new FutureTask(new MyCallable()); //构造一个FutureTask,FutureTask间接继承了Runnable接口
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get());
}

  使用Callable接口相当于在run()方法的基础上再次使用了策略模式,将call()方法留了出来,用以实现并保存方法执行的结果。我们可以看一下源码。

public class FutureTask<V> implements RunnableFuture<V> { //这是FutureTask类,本身间接实现了Runnable接口

  这是FutureTask中的run()方法

public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call(); //可以发现在FutureTask中的run方法中调用了call()方法,而这个call()方法通过构造器传入,我们可以自由实现。相当于也是策略模式的实现。
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result); //在这里将线程运行的结果进行了保存
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
protected void set(V v) {     //这是set()函数
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v; //在这里将返回值赋给了outcome
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
 

4. 总结

  (1)继承Thread类后,我们需要重写run()方法来实现自己的线程。

  (2)对于实现Runnable接口,该接口相当于是策略接口。

  (3)对于实现Callable接口,在FutureTask中给出了run()方法的具体实现(FutureTask间接实现了Runnable接口),并且流出了另外的Callable策略接口来让我们实现可返回值的线程实现。

java中线程的几种实现方式的更多相关文章

  1. java中线程的三种实现方式

    一下记录下线程的3中实现方式:Thread,Runnable,Callable 不需要返回值时,建议使用Runnable:有返回值时建议使用Callable 代码如下所示: package com.f ...

  2. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  3. JAVA中单例模式的几种实现方式

    1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线程安全就不会使用这种方式.但是如果不 ...

  4. 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类

    转自: http://blog.csdn.net/sunguangran/article/details/6069317 非常感谢原作者,整理的这么详细. 在java中可有两种方式实现多线程,一种是继 ...

  5. Java中String对象两种赋值方式的区别

    本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...

  6. Java创建线程的三种主要方式

    Java创建线程的主要方式 一.继承Thread类创建 通过继承Thread并且重写其run(),run方法中即线程执行任务.创建后的子类通过调用 start() 方法即可执行线程方法. 通过继承Th ...

  7. java中线程的几种状态和停止线程的方法

    1.线程的状态图 需要注意的是:线程调用start方法是使得线程到达就绪状态而不是运行状态 2.停止线程的两种方法 1)自然停止:线程体自然执行完毕 2)外部干涉:通过线程体标识 1.线程类中定义线程 ...

  8. 细说java中Map的两种迭代方式

    曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...

  9. Java中Map的4种遍历方式

    第一种方式:这是平常用的最多也最可取的一种遍历方式. for (Map.Entry<String, Object> entry : map.entrySet()) { System.out ...

随机推荐

  1. Linux海量数据高并发实时同步架构方案杂谈

    不论是Redhat还是CentOS系统,除去从CDN缓存或者数据库优化.动静分离等方面来说,在架构层面上,实 现海量数据高并发实时同步访问概括起来大概可以从以下几个方面去入手,当然NFS的存储也可以是 ...

  2. for源码实现

    for源码实现 我们知道,java的while和for基本上是实现一样的功能,这样会不会有一点缺点,同时java的迭代器显得尤为的麻烦. python的for和while就不同了,在实现迭代的功能的情 ...

  3. 使用 SecureRandom 产生随机数采坑记录

    公众号「码海」欢迎关注 背景 我们的项目工程里经常在每个函数需要用到 Random 的地方定义一下 Random 变量(如下) public void doSomethingCommon() { Ra ...

  4. 用Python调用华为云API接口发短信

    [摘要] 用Python调用华为云API接口实现发短信,当然能给调用发短信接口前提条件是通过企业实名认证,而且有一个通过审核的短信签名,话不多说,showcode #!/usr/bin/python3 ...

  5. 带着canvas去流浪系列之七 绘制水球图

    [摘要] 用原生canvasAPI实现百度echarts 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...

  6. 浅议Grpc传输机制和WCF中的回调机制的代码迁移

    浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...

  7. hoverdir

    js 引入  jq  &&  modernizr.custom.97074.js  &&jquery.hoverdir.js css 引入style.css html代 ...

  8. docker等文档

    docker strapi koa express

  9. 结构体与typedef的使用,还有结构体指针的使用(二层结构体指针)

    该类容摘抄自以下链接,为学习之后的记录,不是鄙人原创. 学习链接:https://blog.csdn.net/a2013126370/article/details/78230890 typedef ...

  10. Mybatis的模糊查询以及自动映射

    Mybatis的模糊查询 1.  参数中直接加入%% ? 1 2 3 4 5 6 7 8 9 param.setUsername("%CD%");       param.setP ...