首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【并发那些事】创建线程的三种方式

【并发那些事】创建线程的三种方式

作者头像
KIWI
发布于 2020-04-08 03:48:21
发布于 2020-04-08 03:48:21
35200
代码可运行
举报
文章被收录于专栏:KIWI的碎碎念KIWI的碎碎念
运行总次数:0
代码可运行

创建线程可以说是并发知识中最基础的操作了,JDK 提供的创建线程的方式,如果不包括通过线程池的话,目前有三种形式,它们分别是通过继承 Thread 类,通过实现 Runable 接口,通过 FutureTask。如下图所示

下面整理了一下 3 种方法的具体使用与异同。

创建线程的 3 种方法

1. 继承 Thread
  1. 创建一个类继承 Thread 并覆盖 run 方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyThread extends Thread {

    @Override
    public void run() {
        String threadName = getName();
        for (int i = 0; i < 20; i++) {
            System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());
        }
    }
}
  1. 创建并启动线程
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();

        myThread1.start();
        myThread2.start();

        String threadName = Thread.currentThread().getName();
        for (int i = 0; i < 20; i++) {
            System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());
        }

整体流程如下:

这里步骤比较简单和清晰

  1. 创建一个类,这类要继承 Thread
  2. 覆盖 Thread 的 run 方法,并在此方法中实现你的多线程任务
  3. 创建这个类的实例
  4. 调用它的 start() 方法(这里要注意,新手容易直接调用 run 方法,那样只是普通调用,而不多线程调用)
2. 实现 Runable
  1. 创建一个类实现 Runable 接口,并覆盖 run 方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyRunable implements Runnable {
    
    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        for (int i = 0; i < 20; i++) {
            System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());
        }
    }
}
  1. 创建类的实现,并将它传给 Thread 的构造函数来创建 Thread
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MyRunable myRunable = new MyRunable();

new Thread(myRunable).start();
new Thread(myRunable).start();

String threadName = Thread.currentThread().getName();
for (int i = 0; i < 20; i++) {
    System.out.println("线程[" + threadName + "]运行开始,i = " + i + " time = " + new Date());
}

整体流程如下:

具体步骤如下:

  1. 创建一个实现了 Runable 接口的类
  2. 覆盖 run 方法,并在此方法中实现你的多线程任务
  3. 创建 Runable 接口实现类的实例
  4. 通过把上步得到的 Runable 接口实现类的实例,传给 Thread 的有参构造函数来创建 Thread 的实例
  5. 调用上步得来的 Thread 实例的 start() 方法(这里要注意,新手容易直接调用 run 方法,那样只是普通调用,而不多线程调用)
3. 通过 FutureTask
  1. 创建一个实现了 Callable 接口的类,并实现call 方法 (T 代表你想要的返回值类型)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyCallerTask implements Callable<String> {
    
    @Override
    public String call() throws Exception {
        System.out.println("执行任务开始");
        Thread.sleep(3000);
        System.out.println("执行任务结束");
        return "hello";
    }
}
  1. 创建并启动线程
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 创建异步任务
        FutureTask<String> futureTask = new FutureTask<>(new MyCallerTask());
        // 启动线程
        new Thread(futureTask).start();
        System.out.println("其它操作");
        try {
            // 等待任务执行完,并获得任务执行完的结果
            String result = futureTask.get();
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

整体流程如下:

具体步骤如下:

  1. 创建一个实现了 Callable 接口的类,这里 T 的类型就是你线程任务想要返回的类型
  2. 覆盖 call 方法,并在此方法中实现你的多线程任务
  3. 创建 Callable 接口实现类的实例
  4. 通过把上步得到的 Callable 接口实现类的实例,传给 FutureTask 的有参构造函数来创建 FutureTask 的实例
  5. 通过把上步得到的 FutureTask 实例,传给 Thread 的有参构造函数来创建 Thread 的实例
  6. 调用上步得来的 Thread 实例的 start() 方法(这里要注意,新手容易直接调用 run 方法,那样只是普通调用,而不多线程调用)
  7. 如果你还想获得返回值,需要再调用 **FutureTask **实例的 get() 方法(这里要注意,get()会阻塞线程)

3种方法的优缺点

通过上述的演示代码,可以看出这 3 种方法,其实各有优缺点

复杂程度

通过代码量与逻辑可以明显感觉出来,第一种直接继承 Thread 最方便,并且其它两种到最后,还是要依赖创建 Thread 才能实现。所以从方便及难易程度来看,可以得到如下结论:

可扩展性

通过演示代码可以看出,只有第一种是通过继承,其它两种是通过实现接口的形式。我们都知道 JAVA 是不允许多继承,但是可以多实现。所以如果使用了第一种方法,就无法再继承别的类了。另外第一种把线程与线程任务冗余在了一起,不利于后期的维护。所以可以得到如下结论:

是否有返回值

从代码中可以很容易看出,只有通过 FutureTask 的方式才有返回值,另外两种均没有,所以得出如下结论

该用哪种方式创建线程

如果要用到返回值,那不用想,肯定只能使用 FutureTask 的方法。如果对于返回值没有要求,那Thread 与 Runable 均可,不过,考虑到可扩展性,最好使用 Runable 的形式。不过,话说回来,如果在真正项目中使用,综合考虑,一般还是最推荐通过线程池去创建。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 KIWI的碎碎念 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
java并发基础篇(五): 创建线程的四种方式
在详细了解这四种方法之前,先来理解一下为什么线程要这样创建:形象点来说,Thread是一个工人,run()方法里面的便是他的任务栏,这个任务栏默认是空的。当你想要这个线程做点什么时,你可以重写Thread里面的run方法,重写这个工人的任务栏;也可以通过runable、callable接口,从外部赋予这个工人任务。还可以将任务交给一堆工人,谁有空就谁就承担这个任务(线程池)。
好好学java
2018/08/01
5360
创建线程的三种方式
1)继承Thread类,重写run方法 2)实现Runnable接口创建线程 3)使用Callable和Future创建线程
名字是乱打的
2022/05/13
2730
详解Java中创建线程的四种方式
在 Java 后端开发的面试中,我们经常被问到这样的一道题目:Java 中创建线程的方式有哪些?我们知道 Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例。本文分享以下四种 Java 创建线程的方式:
乔戈里
2019/11/12
6930
创建线程的四种方式
Executors提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
Java架构师必看
2021/07/14
2800
【19】JAVASE-多线程专题【从零开始学JAVA】
Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。
用户4919348
2024/05/25
1620
【19】JAVASE-多线程专题【从零开始学JAVA】
Java中实现多线程的3种方法介绍和比较
一、什么是多线程? 引用网上别人的一段话: 单进程单线程:一个人在一个桌子上吃菜。 单进程多线程:多个人在同一个桌子上一起吃菜。 多进程单线程:多个人每个人在自己的桌子上吃菜。 多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。资源共享就会发生冲突争抢。 使用多线程的优点(相对使用多进程来说): 进程之间不能共享内存,但线程之间共享内存非常容易。 系统创建线程所分配的资源相对创建进程而言,代价非常小。 二、Java中实现多线程的
黄小怪
2018/05/21
7220
创建线程的三种方式优缺点
  Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。
程序员云帆哥
2022/05/12
2540
Java面试之创建线程的三种方法及其区别
然后,调用Thread类的构造函数创建Thread实例并调用start()方法启动线程:
leon公众号精选
2022/04/27
2860
Java面试之创建线程的三种方法及其区别
Java并发编程——创建线程的三种方法以及区别
Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:
向着百万年薪努力的小赵
2022/12/02
2720
创建线程到底有多少种方式?
话不多说,金九银十,很多同学马上就要参加秋招了。而多线程肯定是面试必问的,开篇之前,问大家一个问题:创建线程到底有几种方式?
JavaFish
2020/08/21
4.9K1
多线程(一)-两种创建线程的方式+实现Callable接口方式
​ 继承Thread必须重写run方法,(具体业务执行方法,需要执行的业务方法,定义在此方法中),注意此方法是线程启动后线程自动调用的;
化羽羽
2022/10/28
4470
Java多线程基础知识
进程:一个正在操作系统中运行的exe程序可以理解为一个进程,完全可以将运行在内存中的exe文件理解为进程-----进程就是受操作系统管理的基本运行单元。一个最简单的Java程序的运行也可以叫做一个进程。
害恶细君
2022/11/22
2640
Java多线程基础知识
【80期】说出Java创建线程的三种方式及对比
上述代码中Thread.currentThread()方法返回当前正在执行的线程对象。GetName()方法返回调用该方法的线程的名字。
良月柒
2020/11/06
3890
【80期】说出Java创建线程的三种方式及对比
【Java】创建多线程的四种方式
每个线程都有一定的优先级,同优先级线程组成先进先出队列(先到先服务),使用分时调度策略。优先级高的线程采用抢占式策略,获得较多的执行机会。每个线程默认的优先级都与创建它的父线程具有相同的优先级。
CODER-V
2023/03/04
1.5K0
【Java】创建多线程的四种方式
大数据必学Java基础(七十六):创建线程的三种方式
实际开发中,方式1 继承Thread类 还是 方式2 实现Runnable接口这种方式多呢?
Lansonli
2022/11/06
3160
大数据必学Java基础(七十六):创建线程的三种方式
【Java多线程】:理解线程创建、特性及后台进程
🔥 多线程是提升程序性能非常重要的一种方式,也是Java编程中的一项重要技术。在程序设计中,多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,它们会交替执行,彼此可以通信。
IsLand1314
2024/11/19
3870
【Java多线程】:理解线程创建、特性及后台进程
Java并发编程:如何创建线程?
在 Java 中创建线程的方式有两种:1)继承 Thread 类  2)实现 Runnable 接口 3)实现 FutureTask 接口 前两种方式创建的线程都无法获取线程的执行结果,而通过 FutureTask 方式实现的线程可以获取线程执行的结果。 一、继承Thread类 package com.chanshuyi.thread; public class ThreadDemo1 { public static void main(String[] args) { ne
陈树义
2018/04/13
7430
Java并发编程:如何创建线程?
Java线程的三种创建方法
1、创建Callable接口的实现类, 并实现cal()方法, 该cal()方法将作为线程执行体,并且有返回值。
背雷管的小青年
2021/02/04
6150
Java中实现多线程的四种方式
Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。
Kevin_Zhang
2019/02/20
5660
面试题-实现多线程的方式
每个线程都有自己的票总量,处理的都是自己的票,就是说每个窗口各自卖各自的票,这就是继承实现线程的特点,一个线程处理一件事情
猿天地
2018/07/25
3450
相关推荐
java并发基础篇(五): 创建线程的四种方式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档