多线程详解(一)——创建多线程

2023-10-27

一. 进程与线程:

1. 进程:

进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。

2. 线程:

线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

3. 执行方式:

① 顺序执行:即程序从上往下一步一步的执行
② 并发执行:指两个或多个事件在同一个时间段内执行
③ 并行执行:指两个或多个事件在同一时刻同时执行

二. 创建多线程的三种方式:

1. 继承Thread类:

继承Thread类后要重写Thread类的run()方法,然后调用start()方法开启线程

public class TestThread1 extends Thread{
    public static void main(String[] args) {
        EatThread eatThread = new EatThread();
        DrinkThread drinkThread = new DrinkThread();
        eatThread.start();
        drinkThread.start();
    }
}

class EatThread extends Thread{
    @Override
    public void run() {
        System.out.println("开始吃饭?...\t" + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束吃饭?...\t" + new Date());
    }
}

class DrinkThread extends Thread {
    @Override
    public void run() {
        System.out.println("开始喝酒?...\t" + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束喝酒?...\t" + new Date());
    }
}

此时的运行结果为:
在这里插入图片描述
当把主函数(即主线程)改为run()方法开启线程:

public class TestThread1 extends Thread{
    public static void main(String[] args) {
        EatThread eatThread = new EatThread();
        DrinkThread drinkThread = new DrinkThread();
        eatThread.run();
        drinkThread.run();
    }
}

此时的运行结果为:
在这里插入图片描述
造成区别的原因时:当使用start()方法开启线程时,各线程是并发执行的,当使用run()方法开启线程时,各线程是顺序执行的。
在这里插入图片描述

2. 实现Runnable接口:

与继承Thread类方法类似,实现Runnable接口后要重写run()方法,然后使用Thread类来包装调用start()方法开启线程

public class TestThread2 implements Runnable{
    @Override
    public void run() {
        System.out.println("开始吃饭?...\t" + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束吃饭?...\t" + new Date());
    }

    public static void main(String[] args) {
        TestThread2 t1 = new TestThread2();
        new Thread(t1).start();
        Thread thread = new Thread(t1);  //对同一对象进行多线程从操作
        thread.start();
    }
}

运行结果为:
在这里插入图片描述

注意:
new Thread(t1).start();

Thread thread = new Thread(t1);
thread.start();
这两种写法效果是一样的

第一种方法继承Thread类,Thread类也实现了Runnable接口
第二种方法实现Runnable接口,类似创建一个代理工具类
推荐使用实现Runnable接口的方法实现多线程,可以避免Java单线程的限制

线程开启不一定立即执行,由CPU调度执行

3. 实现Callable接口:

① 实现Callable接口,需要返回值类型
② 重写call()方法,需要抛出异常
③ 创建目标对象 : TestThread3 testThread3 = new TestThread3()
④ 创建执行服务 : ExecutorService ser = Executors.newFixedThreadPool(2)
⑤ 提交执行 : Future r1 = ser.submit(testThread3)
⑥ 获取结果 : boolean rst1 = r1.get();
⑦ 关闭服务 : ser.shutdownNow();

public class TestThread3 implements Callable<Boolean> {  //①实现Callable接口,需要返回值类型
    private String name;

    public TestThread3(String name){
        this.name = name;
    }
    @Override
    public Boolean call() throws Exception {  //②重写call()方法,需要抛出异常
        if(name.equals("张三")){
            System.out.println("欢迎"+name);
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //③创建目标对象
        TestThread3 t1 = new TestThread3("张三");
        TestThread3 t2 = new TestThread3("李四");

        //④创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(2);

        //⑤提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);

        //⑥获取结果
        boolean rst1 = r1.get();
        boolean rst2 = r2.get();
        System.out.println(rst1);
        System.out.println(rst2);

        //⑦关闭服务
        ser.shutdownNow();
    }
}

运行结果:
在这里插入图片描述

三. 多线程实例——龟兔赛跑

public class Race implements Runnable{
    private static String winner;
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            // 模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子") && i%10==0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            boolean flag = isGameOver(i);
            // 如果比赛结束,终止程序
            if (flag){
                break;
            }
            // Thread.currentThread()获取当前线程
            // Thread.currentThread().getName()获取当前线程名字
            System.out.print(Thread.currentThread().getName()+"-->跑了"+i+"步"+"\t");
            if(i%5==0)
                System.out.println();
        }
    }
    // 判断是否有胜利者
    public boolean isGameOver(int step){
        if (winner!=null){
            return true;
        }else{
            if (step>=100){
                winner = Thread.currentThread().getName();
                System.out.println("winner is "+winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

结果:
在这里插入图片描述
参考: https://blog.csdn.net/vbirdbest/article/details/81282163.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程详解(一)——创建多线程 的相关文章

  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O

随机推荐

  • 【mmdetection 】analyze_logs.py等工具测试

    绘制一些运行的分类损失 python tools analyze logs py plot curve work dirs faster rcnn r50 fpn 1x 20200306 175509 log json keys loss
  • 计算机主板南桥的作用,主板南桥是什么,主板南桥芯片在哪?

    主板南桥是什么 主板南桥芯片在哪 笔者稍懂一点电脑硬件 看到网友提问相关方面的问题 很是乐意回答 网络本来就崇尚人人为我 我为人人么 自己这点半瓶水的知识 本来就拜网上高手的科普文章所赐 所以遇到 像主板南桥是什么 主板南桥芯片在哪这类问题
  • QT学习:实现简单的登录登出界面功能

    在设计实现一个系统的时候 用户登录界面的设计可以说是必不可少的环节 而用户登录界面的实现说到底就是不同窗口之间的切换 在继续下面的工作之前 你首先要添加一个新的Qt设计师界面类 记住要选择Dialog without Buttons 否则方
  • Invalid block tag on line 129: ‘get_tag_list‘, expected ‘endblock‘. Did you forget to register or lo

    Django gt python manage py runserver时报错 Invalid block tag on line 129 get tag list expected endblock Did you fo rget to
  • 手把手教Electron+vue,打包vue项目,打包成桌面程序。

    1 现如今前端框架数不胜数 尤其是angular vue吸引一大批前端开发者 在这个高新技术快速崛起的时代 自然少不了各种框架的结合使用 接下来是介绍electron vue的结合使用 2 Electron是什么 对于我来说Electron
  • 最适合读研究生的城市,有你想去的城市吗?

    最适合读研究生的城市 有你想去的城市吗 有没有一座城市让你心生向往 你会因为城市而去选择院校还是因为学校爱上一座城 下面我们就来看一下人气最高 最适合读研的城市 1 北京 北京作为我国的首都 是全国政治文化中心 人称帝都 北京名校众多 既是
  • UML在软件开发各个阶段的应用

    一 UML5个互联视图 UML Unified Modeling Language 中常用5个互联的视图来描述系统的体系结构 如图 1 用例视图 Use case View 由专门描述可被最终用户 分析人员 测试人员看到的系统行为的用例图组
  • Markdown简介

    目录 什么是Markdown Markdown的发展简史 Markdown的基本写法 标题 文本 分隔线 列表 表格 区块 代码段 链接 图片 其他技巧 什么是Markdown Markdown是一种轻量级标记语言 Markdown的写法比
  • web UI 自动化测试:Selenium 语法详解 史上最全

    selenium主要是用来做自动化测试 支持多种浏览器 爬虫中主要用来解决JavaScript渲染问题 模拟浏览器进行网页加载 一 声明浏览器对象 注意点一 Python文件名或者包名不要命名为selenium 会导致无法导入 from s
  • c++ 语法错误 : 缺少“;”(在“*”的前面)

    语法错误 缺少 在 的前面 出现这个错误 我们当然不会考虑简单的原因 就是缺少 在的前面 那么来分析一下可能的不好发现的原因 error C4430 缺少类型说明符 假定为 int 注意 C 不支持默认 int c evan workspa
  • 【mysql】给一张表添加外键的四种方法

    mysql外键 主键 一 添加外键 二 添加主键 一 添加外键 添加外键约束名字一定不能重复 如何添加外键 方法一 直接在属性值后面添加 create table score cscore int 11 st id int 50 refer
  • 关于转换JSON列表错误导致结果出错的问题

    今天修改一个问题 就是不同端封装的不同对象 请求同一个接口 同一个数据 在通用的一个逻辑转换状态中获取到不同的状态的奇葩问题 其实本身两个接口大部分代码是相同的 是直接拷贝过去的 其实就是最后的结果对象参数稍微有点区别 大部分逻辑都是重复的
  • SpringBoot基础入门篇

    文章目录 前言 一 Spring Boot 入门 1 Spring Boot 简介 2 微服务 3 环境准备 1 MAVEN设置 4 Spring Boot HelloWorld 1 创建一个maven工程 jar 2 导入spring b
  • FPGA编程中"打拍"的目的

    版权声明 本文为CSDN博主 qq 33586509 的原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net qq 33586509 article detai
  • quartz 2.3.1源码分析一:创建JobDetail(JobBuilder详解)

    上一篇文章我记录了自己封装的QuartzUtil工具类 同时写了一个quartz骨架项目 以便大家理解使用 点击传送门进入 正文开始 Quartz工具类 创建JobDetail JobBuilder详解 创建CronTrigger Trig
  • 详细前端面试题HTML篇

    CSS篇 JS篇 Vue篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript React 微信小程
  • matlab 遗传优化算法_全局优化

    Building可视库 一起做些更酷的事吧 关注 小库这两天学习有关遗传算法的一些问题 其作为一种全局寻优的智能优化算法 具有很强大的适应性 可以应用于多个领域解决一些最优化的问题 诸如寻路问题 囚犯困境 动作控制 生产调度问题 人工生命模
  • matlab 点云的二进制形状描述子

    目录 一 功能概述 1 算法概述 2 主要函数 3 参考文献 二 代码示例 三 结果展示 四 参数解析 输入参数 名称 值对应参数 输出参数 五 参考链接 本文由CSDN点云侠原创
  • 第七届cuit智能车比赛总结

    作为大一小白 第一次参加比赛 感受到了比赛的氛围 也收获了许多宝贵的经验 1 电磁杆 电磁杆的作用是感应漆包线的位置 给单片机传入数据 使车维持在一定范围内 他的感应部分应用RLC振荡电路 感应到的微弱电流经过一定倍数放大 和滤波电路 最后
  • 多线程详解(一)——创建多线程

    一 进程与线程 1 进程 进程是资源 CPU 内存等 分配的基本单位 它是程序执行时的一个实例 程序运行时系统就会创建一个进程 并为它分配资源 然后把该进程放入进程就绪队列 进程调度器选中它的时候就会为它分配CPU时间 程序开始真正运行 2