多线程概述及创建

什么是线程?

线程(thread)是一个程序内部的一条执行路径。

我们之前启动程序执行后,main方法的执行其实就是一条单独的执行路径。

程序中如果只有一条执行路径,那么这个程序就是单线程的程序。

多线程是什么?

多线程是指从软硬件上实现多条执行流程的技术。

多线程的创建

Thread类

方式一:继承Thread类

1、定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法。

2、创建MyThread类的对象。

3、调用线程对象的start()方法启动线程(启动后还是执行run方法的)。

/**
   目标:多线程的创建方式一:继承Thread类实现。
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        // 3、new一个新线程对象
        Thread t = new MyThread();
        // 4、调用start方法启动线程(执行的还是run方法)
        t.start();

        for (int i = 0; i < 5; i++) {
            System.out.println("主线程执行输出:" + i);
        }

    }
}

/**
   1、定义一个线程类继承Thread类
 */
class MyThread extends Thread{

    public MyThread(){
        super();
    }
    /**
       2、重写run方法,里面是定义线程以后要干啥
     */
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

 

方式二:实现Runnable接口

1、定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法。

2、创建MyRunnable任务对象。

3、把MyRunnable任务对象交给Thread处理。

4、调用线程对象的start()方法启动线程。

**
   目标:学会线程的创建方式二,理解它的优缺点。
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        // 3、创建一个任务对象
        Runnable target = new MyRunnable();
        // 4、把任务对象交给Thread处理
        Thread t = new Thread(target);
        // Thread t = new Thread(target, "1号");
        // 5、启动线程
        t.start();

        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行输出:" + i);
        }
    }
}

/**
   1、定义一个线程任务类 实现Runnable接口
 */
class MyRunnable  implements Runnable {
    /**
       2、重写run方法,定义线程的执行任务的
     */
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("子线程执行输出:" + i);
        }
    }
}

 也可以用匿名内部类形式

/**
   目标:学会线程的创建方式二(匿名内部类方式实现,语法形式)
 */
public class ThreadDemo2Other {
    public static void main(String[] args) {
        Runnable target = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("子线程1执行输出:" + i);
                }
            }
        };
        Thread t = new Thread(target);
        t.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println("子线程2执行输出:" + i);
                }
            }
        }).start();

        new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    System.out.println("子线程3执行输出:" + i);
            }
        }).start();

        for (int i = 0; i < 10; i++) {
            System.out.println("主线程执行输出:" + i);
        }
    }
}

 

方式三:利用Callable、FutureTask接口实现(JDK 5.0新增)

1、得到任务对象

         定义类实现Callable接口,重写call方法,封装要做的事情。

         用FutureTask把Callable对象封装成线程任务对象。

2、把线程任务对象交给Thread处理。

3、调用Thread的start方法启动线程,执行任务 。

4、线程执行完毕后,通过FutureTask的get方法去获取任务执行的结果。

FutureTask的API

 示例

/**
   目标:学会线程的创建方式三:实现Callable接口,结合FutureTask完成。
 */
public class ThreadDemo3 {
    public static void main(String[] args) {
        // 3、创建Callable任务对象
        Callable<String> call = new MyCallable(100);
        // 4、把Callable任务对象 交给 FutureTask 对象
        //  FutureTask对象的作用1: 是Runnable的对象(实现了Runnable接口),可以交给Thread了
        //  FutureTask对象的作用2: 可以在线程执行完毕之后通过调用其get方法得到线程执行完成的结果
        FutureTask<String> f1 = new FutureTask<>(call);
        // 5、交给线程处理
        Thread t1 = new Thread(f1);
        // 6、启动线程
        t1.start();


        Callable<String> call2 = new MyCallable(200);
        FutureTask<String> f2 = new FutureTask<>(call2);
        Thread t2 = new Thread(f2);
        t2.start();

        try {
            // 如果f1任务没有执行完毕,这里的代码会等待,直到线程1跑完才提取结果。
            String rs1 = f1.get();
            System.out.println("第一个结果:" + rs1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            // 如果f2任务没有执行完毕,这里的代码会等待,直到线程2跑完才提取结果。
            String rs2 = f2.get();
            System.out.println("第二个结果:" + rs2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
    1、定义一个任务类 实现Callable接口  应该申明线程任务执行完毕后的结果的数据类型
 */
class MyCallable implements Callable<String>{
    private int n;
    public MyCallable(int n) {
        this.n = n;
    }

    /**
       2、重写call方法(任务方法)
     */
    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n ; i++) {
            sum += i;
        }
        return "子线程执行的结果是:" + sum;
    }
}

3种方式对比

注意事项

1、为什么不直接调用run方法,而是调用start启动线程?

直接调用run方法会当成普通方法执行,此时相当于还是单线程执行。 只有调用start方法才是启动一个新的线程执行,(看start源码)start方法会把线程加入线程组,每个线程都有机会交给cpu执行,这时线程的run方法会被自动调用,每个线程都有可能还没执行完就被中断从而让cpu执行其他线程,。

2、为什么把主线程任务放在子线程之后?

如果把主线程任务放在子线程之前,那么主线程一定是先跑完的,相当于是一个单线程的效果了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 读写权限的配置

文章目录 Linux文件权限详解 一、文件权限二、修改文件访问权限的方法三、UMASK值四、三种特殊权限suid、sgid、sticky&#xff08;sticky权限工作环境中相对常用&#xff09;五、ACL访问控制列表六、文件权限操作的常用命令 Linux文件权限详解 Linux系统中不仅是对用户与组根…

Cesium 实战 - 加载水经微图下载资源问题 - 地球南北极有蓝圈,南北极空洞

Cesium 实战 - 加载水经微图下载资源问题 - 地球南北极有蓝圈 错误展示排错过程解决问题完整代码在线示例 在某个项目中&#xff0c;客户提到一个问题&#xff0c;即地球南北极会有一个蓝色的洞&#xff0c;经复现&#xff0c;确实有这个问题。见下图。 经过排查&#xff0c;最…

高难度工业废水处理有哪些注意事项

高难度工业废水处理的注意事项包括&#xff1a; 预处理&#xff1a;在将废水输送至污水处理系统前&#xff0c;应进行预处理&#xff0c;以减轻处理设备的负荷&#xff0c;提高处理效率。预处理可以包括去除废水中的悬浮物、沉淀物以及防止化学物质的沉积等。针对不同废水选择…

nestJs(三) 数据库

真正的服务往往包括数据存储。 本篇将介绍如何建立 NestJs 的数据库连接、并使用数据库联表查询。这样就就是完整的后台服务了。 开发准备 下载并安装 Mysql创建 school 库 create database school;3.安装 nestjs/typeorm typeorm mysql2 npm install --save nestjs/typeor…

浅了解下:运营商大数据如何挖掘电销同行网站,APP,精准获客 ?

今天我们要讲的是运营商精准大数据营销。运营商精准大数据营销只是精准营销的一种&#xff0c;精准营销筛选包含了电话营销这个词。那么电话营销如何通过运营商大数据找到精准的客户&#xff1f;电销如何通过大数据找到准确的客户来源&#xff1f; 在全网时代&#xff0c;大数…

echarts:graph图表拖拽节点

需求&#xff1a;实现一个可视化编辑器&#xff0c;用户可以添加节点&#xff0c;并对节点进行拖拽编辑等 实现期间碰到很多问题&#xff0c;特意记录下来&#xff0c;留待将来碰到这些问题的同学&#xff0c;省去些解决问题的时间 问题1&#xff1a;节点的data如下&#xff0…

无需管理底层基础设施,亚马逊云科技向量数据库轻松创建ML增强的搜索体验和应用程序

当我们进入一家图书馆时&#xff0c;图书馆的入口处会有几台电脑供你检索相关的书籍&#xff0c;你可以检索你想要的书籍的名字例如&#xff1a;《百年孤独》、《悲惨世界》等等&#xff0c;你也可以检索作者例如&#xff1a;川端康成、鲁迅、加缪等等&#xff0c;当然你也可以…

读书充电,温暖你的冬日,本期为大家送出几本架构师成长和软件架构技术相关的好书,助你度过这个不太景气的寒冬!

目图书录 ⭐️《高并发架构实战&#xff1a;从需求分析到系统设计》⭐️《架构师的自我修炼&#xff1a;技术、架构和未来》⭐️《中台架构与实现&#xff1a;基于DDD和微服务》⭐️《分布式系统架构&#xff1a;架构策略与难题求解》⭐️《流程自动化实战&#xff1a;系统架构…

家电制造产线物料追踪RFID智能管理解决方案

家电行业需求 家电行业的生产节奏快&#xff0c;供应商众多&#xff0c;导致入厂车辆经常出现拥堵和等待的情况&#xff0c;生产线可能因为关键零部件物流未到位而停产&#xff0c;传统的家电制造行业生产物流模式主要依赖人工进行零部件的存储、拣选、配送、核对和发放等环节…

中国唯一!华为入选Gartner®企业低代码应用平台魔力象限

近日&#xff0c;全球咨询机构Gartner发布 《Magic Quadrant™ for Enterprise Low-Code Application Platforms》报告&#xff0c;华为入选该象限&#xff0c;作为中国唯一入选厂商&#xff0c;华为已连续两年入选Gartner企业低代码应用平台魔力象限。 华为云Astro低代码平台采…

动态获取填充表格数据时的特定值的赋值

1、如图 <el-tablev-loading"loading":data"columnList"bordertooltip-effect"dark":size"tableSize":height"tableHeight"style"width: 100%; margin: 15px 0"><el-table-column type"selection…

【MySQL】随手笔记(积跬步至千里)

一、常用函数 &#xff08;1&#xff09;uuid() select uuid(); //生成随机数 select replace(uuid(),-,); //将随机数的-去掉 select upper(replace(uuid(),-,)); ///改成大写应用举例&#xff1a; &#xff08;1&#xff09;非自增主键 非自增主键&#xff0c;insert语…

优化奥德赛:揭开训练人工神经网络的本质

一、介绍 近年来&#xff0c;人工智能领域取得了显著的进步&#xff0c;而这场革命的核心是训练人工神经网络 &#xff08;ANN&#xff09; 的复杂过程。这些网络受到人脑的启发&#xff0c;能够从数据中学习复杂的模式和表示。人工神经网络成功的核心是认识到训练它们从根本上…

Blackmagic Design DaVinci Resolve Studio18(达芬奇调色剪辑)mac/win中文版

在影视制作领域&#xff0c;调色和剪辑是至关重要的环节&#xff0c;它们直接决定了作品的观感和质量。而Blackmagic Design DaVinci Resolve Studio18&#xff08;达芬奇调色剪辑&#xff09;作为业界领先的专业调色剪辑软件&#xff0c;以其出色的性能和强大的功能&#xff0…

【Python】operator模块

Python中operator模块提供了一套与 Python 的内置运算符对应的高效率函数。 不仅对应内置运算符&#xff0c;还可以获取方法。可优化涉及回调函数的运算性能&#xff0c;比lambda、Python函数的开销小、速度快。 import operator[x for x in dir(operator) if not x.startswi…

【Linux】-文件系统的详解以及软硬链接

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

实现高值医疗耗材智能化管理的RFID医疗柜解决方案

一、行业背景 医疗物资管理面临着一系列问题&#xff0c;如高值耗材种类激增导致准入标准弱化、信息追踪困难、管理责任不明确等&#xff0c;医院内部设备、财务和临床科室相互独立&#xff0c;兼容性不佳&#xff0c;高值耗材储备不足&#xff0c;缺乏合理的预警机制&#xf…

卡尔曼家族从零解剖-(06) 一维卡尔曼滤波编程(c++)实践、透彻理解公式结果

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…

go语言学习之旅之go语言基础语法

学无止境&#xff0c;今天学习go语言的基础语法 行分隔符 在 Go 程序中&#xff0c;一行代表一个语句结束。没有结束符号 注释 注释不会被编译&#xff0c;每一个包应该有相关注释。 单行注释是最常见的注释形式&#xff0c;你可以在任何地方使用以 // 开头的单行注释。多…

淘宝账单导出的手工操作

文章目录 淘宝账单导出的手工操作概述笔记END 淘宝账单导出的手工操作 概述 日常的支付(JD, 淘宝, 1688), 最终都是用微信和支付宝来支付. 微信和支付宝是绑定的自己银行卡. JD绑定的也是自己的银行卡. 微信账单的导出, 已经记录了, 好使. 现在记录一下支付宝账单(只要是阿…