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. java 静态变量&静态方法

    1. 静态变量是static修饰的成员变量(类变量),若无static修饰,则是实例变量.静态变量是一种全局变量,它属于某个类,不属于某个对象实例,是在各对象实例间共存.   访问静态变量直接通过类名 ...

  2. 第二章 Unity Shader基础

    [TOC] 1. Unity Shader 的基础: ShaderLab 学习和编写着色器的过程一直是一个学习曲线很陡峭的过程,通常情况下为了自定义渲染效果往往要和很多文件和设置打交道,这些设置很容易 ...

  3. 【开发记录】Linux常用命令记录(一)【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  4. BOM对象中的常用方法

    先看body中的内容: <body οnlοad="demo1()"> <p> <input type="button" id=& ...

  5. Pandas里面常用的一些数据分析函数总结

    import pandas as pdimport numpy as np pandas 有两个主要的数据结构:Series 和 DataFrame:Series 是一个一维数组对象 ,它包含一组索引 ...

  6. (全国多校重现赛一)D Dying light

    LsF is visiting a local amusement park with his friends, and a mirror room successfully attracts his ...

  7. UESTC-1963咸鱼咕咕咕(二分图匹配)

    咸鱼咕咕咕 Time Limit: 1000 MS     Memory Limit: 64 MB Submit Status 咸鱼有个咕咕笼. 咕咕笼可以划分成m×nm×n个格子,每个小格子可以放下 ...

  8. Node笔记 - process.cwd() 和 __dirname 的区别

    process.cwd() 返回工作目录  __dirname 返回脚本所在的目录位置 单看概念觉得都差不多,有种似懂非懂的感觉,那么接下用一个简单易懂的例子来理解下这两者的区别,在此之前先看一个方法 ...

  9. 通过ansible自动化部署zabbix应用

    zabbix在实际的应用中,可能需要监控的主机非常多,而每个主机的操作系统类型.版本也都不尽相同,在这种环境下,通过手动安装zabbix的agent端已经不现实了,此时就需要借助自动化工具完成zabb ...

  10. python输出日志到文件(每天一个日志)

    import logging from logging.handlers import TimedRotatingFileHandler logger = logging.getLogger('sim ...