实现多线程的三种方式

news2024/9/28 7:18:15

1. 继承Thread 类实现多线程

想要实现多线程,第一种方法就是通过继承Thread类实现多线程,有以下几步

(1)我们要先自定义一个类然后继承Thread类;

(2)在继承Trread的类中重写 run 方法;

(3)通过创建该类的对象即可创建线程,创建多个对象就可以实现多线程;

(4)这种实现多线程的方式无法获取多线程的结果;

如下代码,我先定义了一个ThreadTest01类

// 创建一个类继承 Thread 类
public class Thread01 extends Thread{
    // 重写 run 方法
    @Override
    public void run(){
        for (int i = 0; i < 5; i++) {
            // 通过getName() 获取线程名称
            System.out.println(getName()+"多线程");
        } 
    }
}

我们在另一个类中写一个 main 方法,创建 ThreadTest01类的对象,然后就可以实现多线程,代码如下;

public class TestThread01 {
    public static void main(String[] args) {
        // 创建线程 t1
        Thread01 t1 = new Thread01();
        // 创建线程 t2
        Thread01 t2 = new Thread01();

        // 给 t1 线程添加一个名字做区分
        t1.setName("线程1");
        // 给 t2 线程添加一个名字做区分
        t2.setName("线程2");

        // 通过 start 启动线程
        t1.start();
        t2.start();
    }
}

运行上述 main 方法,即可在在控制台中得到如下结果

我们可以看到,线程1与线程2交替执行,最终都进行完成,这就做到了多线程的效果。

2. 实现 Runnable 接口的方式实现多线程

通过实现 Runnable 接口的方式实现多线程也大致可以分为以下几步

(1)自定义一个了类实现 Runnable 接口;

(2)重写 run 方法;

(3)创建自定义类的对象;

(4)创建 Thread 类对象,将自定义对象作为参数传递给 Thread对象;

(5)通过调用 start 方法启动线程实现多线程;

(6)这种实现多线程的方式也无法获取多线程的结果。

代码如下所示,首先先定义一个自定义类实现 Runnable 接口,重写run方法。

// 创建一个类实现 Runnable 接口
public class Thread02 implements Runnable{
    // 重写 run 方法
    @Override
    public void run(){
        for (int i = 0; i < 5; i++) {
            /**
             * 这里有一个点需要注意,刚才我们通过继承 Thread 实现多线程,
             * 之所以可以通过 getName()方法获取线程名称,是因为getName()方法时 Thread 类中的,
             * 子类可以直接使用父类中的方法。
             * 但现在我们是实现 Runnable 接口实现多线程,就不能也无法直接调用 getName() 方法获取线程名称
             * 但我们可以再创建一个 Thread 类的对象,接收当前线程对象
             * 然后再使用 getName() 方法获取当前线程对象名称
             * 这一点需要注意哦!!!
             */
            // 创建对象 t 获取当前线程对象
            Thread t = Thread.currentThread();
            // 获取当前线程名称
            System.out.println(t.getName() +"多线程");//getName()
        }
    }
}

然后去另一个测试类写 main 方法测试多线程,代码如下

public class TestThread02 {
    public static void main(String[] args) {
        // 创建线程 Thread02的对象
        Thread02 t1 = new Thread02();
        // new 一个线程,将 t1 作为参数传递进去
        Thread thread01 = new Thread(t1);

        // 创建线程 thread02 的对象
        Thread02 t2 = new Thread02();
        // 再 new 一个线程,将 t2 作为参数传递进去
        Thread thread02 = new Thread(t2);

        // 给 t1 线程添加一个名字做区分
        thread01.setName("线程1");
        // 给 t2 线程添加一个名字做区分
        thread02.setName("线程2");

        // 通过 start 启动线程
        thread01.start();
        thread02.start();
    }
}

运行 main 方法,即可在控制台得到如下结果,因为我循环次数较少,可能效果不明显,各位小伙伴自行测试的时候可以把 for 循环次数增多,会更加直观一些!

3. 利用 Callable 和 Future 接口实现多线程

其实这第三种方式是对前两种实现多线程方式的补充,我们可以发现,前两种方法实现多线程时,重写 run 方法,返回值都是 viod ,因此无法获取多线程的执行结果,而这第三种方法就可以。

大致分为以下几步

(1)创建一个自定义类实现 Callable 接口;

(2)重写 call ,(有返回值的,表示多线程的运行结果);

(3)创建自定义类的对象,执行要执行的任务;

(4)创建 Future 的对象,它可以管理多线程运行的结果,但是 Future 是一个接口,所以我们需要创建它的是实现类 FutureTask 的对象。

(5)创建 Thread 的对象,并调用 start 启动线程。

先创建一个类实现 Callable 接口,如下代码所示

// 创建一个类实现 Callable 接口,这里要注意,Callable需要传递一个泛型,表示运行的结果类型
public class Thread03 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        // 随便写一段逻辑,求 1~100 的 整数和
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum = sum + i;
        }
        // 将计算的结果返回
        return sum;
    }
}

我们去另一个类编写 main 方法测试这种带有返回值的多线程的方法,代码如下所示

public class TestThread03 {
    public static void main(String[] args) {
        // 创建线程 Thread03的对象
        Thread03 t1 = new Thread03();
        // 将创建的 t1 对象作为参数传递给 FutureTask
        FutureTask<Integer> futureTask = new FutureTask<>(t1);
        // 创建 Thread 对象,并把 futureTask 作为参数的传递进去
        Thread thread = new Thread(futureTask);

        // 通过 start 启动线程
        thread.start();

        // 获取线程的结果,有异常使用 try。。。catch。。。
        try {
            Integer num = futureTask.get();
            System.out.println(num);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

运行 main 方法,即可在控制台得到1~100 的结果,如下所示

4. 总结概括

(1)实现多线程有三种方式,一是继承 Thread 类,二是实现 Runnable 接口,三是实现 Callable接口并利用 FutureTask 类接收线程结果。

(2)继承 Thread 类实现多线程不可以获取线程的结果;实现 Runnable 接口实现多线程的方式也无法获取返回值结果。

(3)我们都知道,继承只能单继承,而接口却可以多实现。

因此不难看出,第一种继承 Thread 类实现多线程的方式是不太友好地,虽然编程较为简单,但是可扩展性较差,一旦我们的业务类还需要继承别的类,就不行了。

而第二种与第三种方式,均是通过实现接口的方式来实现多线程的,也可以继承其他类实现其他接口,虽然编写过程较复杂,但可扩展性强,但是也无法直接使用 Thread 类中的方法了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/838078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

成功了!|| Poetry安装pytorch || 整理自github项目Poetry下的issue

在使用Poetry安装pytorch的时候&#xff0c;常常会遇到各种问题&#xff1a;首先是使用add添加时&#xff0c;会说只有torch没有什么pytorch&#xff0c;很显然&#xff0c;它是直接针对包的&#xff0c;第二点是&#xff0c;如果是一台没有nvidia显卡的机器&#xff0c;由于po…

CISA《网络安全事件和漏洞响应手册》提到的SSVC是什么?

2021年11月16日&#xff0c;美国网络安全和基础设施安全局(CISA)根据行政命令EO 14028的要求发布了《网络安全事件和漏洞响应手册》。手册规定的漏洞响应过程包括识别、评估、修复、报告通知4个步骤&#xff0c;其中评估部分的第一句话提到“使用特定相关者漏洞分类法(Stakehol…

C++ 动态内存分配

在C中动态内存的分配技术可以保证程序在允许过程中按照实际需要申请适量的内存&#xff0c;使用结束后还可以释放&#xff0c;这种在程序运行过程中申请和释放的存储单元也称为堆。 申请和释放过程一般称为建立和删除。 在C程序中&#xff0c;建立和删除堆对象使用两个运算符&…

html页面input设置日期和时分秒组件方法

html <input class"form-control" type"datetime-local" step"01">效果图

Java根据坐标经纬度计算两点距离(5种方法)、校验经纬度是否在圆/多边形区域内的算法推荐

目录 前言 一、根据坐标经纬度计算两点距离&#xff08;5种方法&#xff09; 1.方法一 2.方法二 3.方法三 4.方法四 5.方法五 5.1 POM引入第三方依赖 5.2 代码 6.测试结果对比 二、校验经纬度是否在制定区域内 1.判断一个坐标是否在圆形区域内 2.判断一个坐标是否…

安防监控国标GB28181平台EasyGBS视频快照无法显示是什么原因?如何解决?

安防视频监控国标视频云服务EasyGBS支持设备/平台通过国标GB28181协议注册接入&#xff0c;并能实现视频的实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强&#xff0c;支持将接入的视频流进行全终端、全平台分发&#xff…

【Leetcode刷题】模拟

本篇文章为 LeetCode 模拟模块的刷题笔记&#xff0c;仅供参考。 目录 一. 字符串Leetcode43.字符串相乘Leetcode592.分数加减运算Leetcode68.文本左右对齐 二. 矩阵Leetcode54.螺旋矩阵Leetcode885.螺旋矩阵 IIILeetcode498.对角线遍历Leetcode874.模拟行走机器人 三. 数组Lee…

Aligning Large Language Models with Human: A Survey

本文也是LLM相关的综述文章&#xff0c;针对《Aligning Large Language Models with Human: A Survey》的翻译。 对齐人类与大语言模型&#xff1a;综述 摘要1 引言2 对齐数据收集2.1 来自人类的指令2.1.1 NLP基准2.1.2 人工构造指令 2.2 来自强大LLM的指令2.2.1 自指令2.2.2 …

JavaSE【抽象类和接口】(抽象类、接口、实现多个接口、接口的继承)

一、抽象类 在 Java 中&#xff0c;一个类如果被 abstract 修饰称为抽象类&#xff0c;抽象类中被 abstract 修饰的方法称为抽象方法&#xff0c;抽象方法不用 给出具体的实现体。 1.语法 // 抽象类&#xff1a;被 abstract 修饰的类 public abstract class Shape { …

AI.com的命运之战:马斯克如何从OpenAI手中夺走这个价值千万的域名

一、AI.COM AI.com是一个极具价值的域名&#xff0c;它于1993年5月注册&#xff0c;距今已有近30年的历史。2021年2月&#xff0c;人工智能研究机构OpenAI以至少1100万美元&#xff08;约合人民币7535万元&#xff09;的高价&#xff0c;拿下了这个域名。OpenAI是马斯克在2015…

微信小程序中的分包使用介绍

一、分包的好处 可以优化小程序首次启动的下载时间 在多团队共同开发时可以更好的解耦协作 主包&#xff1a;放置默认启动页面/TabBar 页面&#xff0c;公共资源/JS 脚本 分包&#xff1a;根据开发者的配置进行划分 限制&#xff1a;所有分包大小不超过 20M&#xff0c;单…

私有化部署企业IM即时通讯:提升效率、防止泄密、高效协同办公

随着科技的飞速发展和智能手机的普及&#xff0c;即时通讯&#xff08;IM&#xff09;应用在我们的生活和工作中变得越来越重要。在企业中&#xff0c;IM已成为员工之间交流沟通的主要方式之一。然而&#xff0c;对于大多数企业来说&#xff0c;选择私有化部署企业IM即时通讯软…

Pytorch Tutorial【Chapter 2. Autograd】

Pytorch Tutorial 文章目录 Pytorch TutorialChapter 2. Autograd1. Review Matrix Calculus1.1 Definition向量对向量求导1.2 Definition标量对向量求导1.3 Definition标量对矩阵求导 2.关于autograd的说明3. grad的计算3.1 Manual手动计算3.2 backward()自动计算 Reference C…

解决在mybatis中使用class属性绑定映射文件出现的异常问题~

如下所示&#xff0c;当我在XML文件中通过class属性配置其mapper文件时&#xff0c;出现下述错误 <mappers><mapper class"mappers.userMapper"/> </mappers>错误描述&#xff1a; 解决方法如下所示&#xff1a;在pom.xml文件中添加下述代码 <…

【腾讯云Cloud Studio实战训练营】使用React快速构建点餐H5

文章目录 前言一、Cloud Studio是什么二、Cloud Studio特点三、Cloud Studio使用1.访问官网2.账号注册3.模板选择4.模板初始化5.H5开发安装 antd-mobile安装 Less安装 normalize&#xff1a;上传项目需要的素材&#xff1a;替换App.js主文件&#xff1a;项目启动、展示 6.发布仓…

zookeeper安装教程及其基本使用

目录 zookeeper下载&#xff1a; zookeeper下载官网&#xff1a; 本地安装配置&#xff1a; 启动zookeeper&#xff1a; 开启服务端&#xff1a; 启动客户端&#xff1a; 查看zookeeper的状态&#xff1a; zoo.cfg文件解读&#xff1a; zookeeper的集群安装&#xff1a…

Go调试神器pprof使用教程【实战分享】

Go调试神器pprof使用教程 go的GC会自动管理内存&#xff0c;但是这不代表go程序就不会内存泄露了。 go常见产生内存泄露的原因就是goroutine没有结束&#xff0c;简单说就是goroutine 被阻塞了&#xff0c;这样就会导致goroutine引用的内存不被GC回收。 1 概念 在Go中&#xf…

二叉树的性质、前中后序遍历【详细】

1. 树概念2.二叉树的概念1.2二叉树的性质 3.二叉树遍历3.2前序遍历3.2 中序遍历3.3 后序遍历 1. 树概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合&#xff0c;有二叉树&#xff0c;N叉树等等。 子树…

[CKA]考试之一个 Pod 封装多个容器

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 创建一个Pod&#xff0c;名字为kucc1&#xff0c;这个Pod包含4容器&#xff…