java中多线程

news2025/3/10 14:49:10

文章目录

  • 多线程
    • 进程和线程
      • 进程
      • 线程
    • 继承Thread类方式实现多线程
    • 设置线程名字的两个方式
    • 获取正在运行的线程
    • 线程调度模型和线程优先级设置
      • 两种调度模型
      • 优先级设置
    • 线程控制
      • sleep
      • join
      • 守护线程
    • 线程生命周期


多线程

进程和线程

进程

进程:是正在运行的程序

  • 是系统进行资源分配和调用的独立单位

  • 每个进程都具有它自己的存储空间和系统资源

线程

线程:是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进程如果只有一条执行路径,则称之为单线程程序

  • 多线程:一个进程如果有多条执行路径,则称之为多线程程序

继承Thread类方式实现多线程

  • 继承 Thread 类

  • 定义一个 MyThread 继承 Thread 类

  • 在 MyThread 类中重写 run() 方法

  • 创建 MyThread 类的对象

  • 启动线程

demo:

定义一个名字为MyThread的类继承Thread类,重新里面的run方法

package com.itxs.demo01;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    @Override
    // 当线程被启动时,会自动调用run方法
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("i = " + i);
        }
    }
}

创建测试类demo01

package com.itxs.demo01;

/**
 * @Classname : demo01
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
         // 创建线程对象
        MyThread mt01 = new MyThread();
        MyThread mt02 = new MyThread();
        MyThread mt03 = new MyThread();
         // 通过start方法来启动多线程
        mt01.start();
        mt02.start();
        mt03.start();
    }
}

运行结果:每个线程里面都是执行三次循环,并没有顺序,而是谁抢到谁执行,
在这里插入图片描述

设置线程名字的两个方式

  1. 调用方法setName()来设置线程名字
  2. 通过构造方法来设置线程名字

demo:

自定义的线程类

package com.itxs.demo01;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    // 无参构造
    public MyThread() {
        super();
    }

    /**
     * 带参数构造,设置每个线程名字
     * @param name 名字
     */
    public MyThread(String name) {
        super(name);
    }

    @Override
    // 当线程被启动时,会自动调用run方法
    public void run() {
        for (int i = 0; i < 3; i++) {
            // this当前类,getName表示获取当前类的名字
            System.out.println(this.getName() + " i = " + i);
        }
    }
}

测试类demo01

package com.itxs.demo01;

/**
 * @Classname : demo01
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
         // 创建线程对象
        MyThread mt01 = new MyThread("线程01");
        MyThread mt02 = new MyThread("线程02");
        MyThread mt03 = new MyThread();
        // 设置每个线程的名字的方法setName();
//        mt01.setName("线程01");
//        mt02.setName("线程02");
        mt03.setName("线程03");
         // 通过start方法来启动多线程
        mt01.start();
        mt02.start();
        mt03.start();
    }
}

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

获取正在运行的线程

调用下面Thread类中方法,可以获取当前正在运行对象

Thread.currentThread()

main也是一个线程,设置main线程名字,没有办法通过this.getName和this.setName进行设置,只能通过上面的Thread类中方法进行设置获取

demo:

注意run方法中,输出每个线程名字的地方调用了Thread.currentThread()

package com.itxs.demo01;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    // 无参构造
    public MyThread() {
        super();
    }

    /**
     * 带参数构造,设置每个线程名字
     * @param name 名字
     */
    public MyThread(String name) {
        super(name);
    }

    @Override
    // 当线程被启动时,会自动调用run方法
    public void run() {
        for (int i = 0; i < 3; i++) {
            // this当前类,getName表示获取当前类的名字
           // System.out.println(this.getName() + " i = " + i);
             System.out.println(Thread.currentThread().getName() + " i = " + i);
        }
    }
}

测试类demo01: 注意main线程获取的

package com.itxs.demo01;

/**
 * @Classname : demo01
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
         // 创建线程对象
        MyThread mt01 = new MyThread("线程01");
        MyThread mt02 = new MyThread("线程02");
        MyThread mt03 = new MyThread();
        // 设置每个线程的名字的方法setName();
//        mt01.setName("线程01");
//        mt02.setName("线程02");
        mt03.setName("线程03");
         // 通过start方法来启动多线程
        mt01.start();
        mt02.start();
        mt03.start();
        // 获取正在运行的线程对象
        Thread.currentThread().setName("主线程");// 设置main线程名字
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "i = " + i);
        }
    }
}

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

线程调度模型和线程优先级设置

两种调度模型

  • 两种线程调度模型

    • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间

    • 抢占调度模型:优先让优先级高的线程使用 CPU,如果线程的欧优先级相同,那么随机选择一个,优先级高的线程获取的 CPU 占用时间会相对多一些

    Java 使用的是抢占式的调度模型

优先级设置

Thread 类中设置和获取线程优先级的方法

 getPriority()//返回次线程的优先级
 setProiority()//更改次线程的优先级

demo:

创建一个名字为MyThread类继承Thread类

package com.itxs.demo01;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    // 无参构造
    public MyThread() {
        super();
    }

    /**
     * 带参数构造,设置每个线程名字
     * @param name 名字
     */
    public MyThread(String name) {
        super(name);
    }

    @Override
    // 当线程被启动时,会自动调用run方法
    public void run() {
        for (int i = 0; i < 50; i++) {
            // this当前类,getName表示获取当前类的名字
           // System.out.println(this.getName() + " i = " + i);
             System.out.println(Thread.currentThread().getName() + " i = " + i);
        }
    }
}

测试类demo02 - 查看优先级高的线程是否能更快执行完

package com.itxs.demo01;

/**
 * @Classname : demo02
 * @Description : TODO 线程优先级测试运行结果
 * @Author : lin_refuel@qq.com
 */
public class demo02 {
    public static void main(String[] args) {
         // 创建线程
        MyThread mt01 = new MyThread("线程01");
        MyThread mt02 = new MyThread("线程02");
        MyThread mt03 = new MyThread("线程03");
         // 设置每个线程优先级
        mt01.setPriority(Thread.MIN_PRIORITY);// 优先级低
        mt02.setPriority(Thread.NORM_PRIORITY);// 优先级不变
        mt03.setPriority(Thread.MAX_PRIORITY); // 优先级最高
        // 输出每个线程优先级
//        System.out.println(mt01.getPriority());//1
//        System.out.println(mt02.getPriority());//5
//        System.out.println(mt03.getPriority());//10
        // 开启线程
        mt01.start();
        mt02.start();
        mt03.start();
    }
}

运行结果: 线程mt03比其他两个线程运行快一点,仅仅一点

线程控制

sleep

sleep:使当前正在执行的线程停留指定的毫秒数

demo:案例:华山论剑

定义一个MyThread类继承Thread类

package com.itxs.demo02;

/**
 * @Classname : MyThread
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
        super();
    }

    // 初始化线程名字的构造方法
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 1; i <= 20; i++) {
            System.out.println(Thread.currentThread().getName() + "打出了第" + i + "招");
            // 调用sleep使其线程执行一次循环后停留1秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

sleeptest测试类

package com.itxs.demo02;

/**
 * @Classname : sleepTest
 * @Description : TODO sleep测试类
 * @Author : lin_refuel@qq.com
 */
public class sleepTest {
    public static void main(String[] args) {
        // 创建线程对象
        MyThread mt01 = new MyThread("黄固");
        MyThread mt02 = new MyThread("欧阳锋");
        MyThread mt03 = new MyThread("段智兴");
        MyThread mt04 = new MyThread("洪七公");
        // 开启线程
        mt01.start();
        mt02.start();
        mt03.start();
        mt04.start();
    }
}

join

join:等待线程结束

package com.itxs.demo03;

/**
 * @Classname : MyThread
 * @Description : TODO 自定义线程类 - 继承Thread类
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
        super();
    }
    // 设置线程名字
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName()+"报数:"+i);
        }
    }
}

test:测试类,注意join的使用,需要抛出异常

package com.itxs.demo03;

/**
 * @Classname : test
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class test {
    public static void main(String[] args) throws InterruptedException {
         // 三个人报数,第一个人报完数后,其他人才能报数
        MyThread mt01 = new MyThread("1号");
        MyThread mt02 = new MyThread("2号");
        MyThread mt03 = new MyThread("3号");
        // 开始报数
        mt01.start();
        mt01.join();//等待第一个人报数完毕
        mt02.start();
        mt03.start();
    }
}

守护线程

setDaemon(boolean on)

将此线程标记为守护进程,当运行线程都是守护线程时,JVM 将退出

个人理解:主线程里面运行结束,守护线程不会继续执行

例子:老板带三个员工吃饭,老板吃饱后,员工不能继续吃了

demo:

定义MyThread类继承Thread类

package com.itxs.demo04;

/**
 * @Classname : MyThread
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class MyThread extends Thread {
    public MyThread() {
        super();
    }

    // 设置线程对象名字
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 1; i <= 50; i++) {
            System.out.println(Thread.currentThread().getName() + "正在吃" + i + "口");
        }
    }
}

定义三个线程设置为守护线程,进行测试,注意守护线程设置方式

package com.itxs.demo04;

/**
 * @Classname : test
 * @Description : TODO
 * @Author : lin_refuel@qq.com
 */
public class test {
    public static void main(String[] args) {
        // 创建三个工人线程
        MyThread mt01 = new MyThread("1号工人");
        MyThread mt02 = new MyThread("1号工人");
        MyThread mt03 = new MyThread("1号工人");
        System.out.println("吃饭了");

        // 三个工人线程设置为守护线程,老板说吃饱了,工人就不继续吃了
        mt01.setDaemon(true);
        mt02.setDaemon(true);
        mt03.setDaemon(true);
        mt01.start();
        mt02.start();
        mt03.start();
        // 主线程:作为老板
        Thread.currentThread().setName("老板");
        for (int i = 1; i <5; i++) {
            System.out.println(Thread.currentThread().getName() + "正在吃第" + i + "口");
        }
        System.out.println("老板说吃饱了,咱们走吧");
    }
}

线程生命周期

  • 新建:创建线程对象(通过 start() 进入下一个环节)

  • 就绪:有执行资格,没有执行权(抢占 CPU 的执行权)

  • 运行:有执行资格,有执行权(可能被其他线程抢走 CPU 的执行权,则回到就绪状态,若遇到阻塞式方法,则失去运行权和执行这个,等待,当阻塞方法调用结束之后,回到就绪状态)

  • 死亡:线程死亡,成为垃圾

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

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

相关文章

【非监督学习 02】高斯混合模型

高斯混合模型&#xff08;Guassian Mixed Model, GMM&#xff09;也是一种常见的聚类算法&#xff0c;与K均值算法类似&#xff0c;同样使用了EM算法进行迭代计算。高斯混合模型假设每个簇的数据都是符合高斯分布的&#xff0c;当前数据呈现的分布就是各个簇的高斯分布叠加在一…

手写Webpack-Plugin

Plugin原理 一、Plugin作用 通过插件我们可以扩展webpack&#xff0c;使webpack可以执行更广泛的任务&#xff0c;拥有更强的构建能力。 Plugin工作原理 webpack 就像一条生产线&#xff0c;要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程…

亚马逊时尚如何运用人工智能帮助您找到合适的尺码

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

React16源码: React中的schedule调度整体流程

schedule调度的整体流程 React Fiber Scheduler 是 react16 最核心的一部分&#xff0c;这块在 react-reconciler 这个包中这个包的核心是 fiber reconciler&#xff0c;也即是 fiber 结构fiber 的结构帮助我们把react整个树的应用&#xff0c;更新的流程&#xff0c;能够拆成…

GitHub Copilot的使用方法和快捷按键

GitHub Copilot是GitHub与OpenAI合作开发的一款人工智能编码助手。它基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型&#xff0c;可以为你提供代码补全、建议和生成的功能 使用方法&#xff1a; 安装插件&#xff1a; 首先&#xff0c;确保你的开发环…

二阶构造设计模式

目录 构造函数回顾 深入思考 实验 构造函数的真相 半成品对象 引入二阶构造设计模式 设计理念 二阶构造设计模式图 二阶构造示例 完整demo 小结 构造函数回顾 类的构造函数用于对象的初始化。构造函数与类同名并且没有返回值。构造函数在对象定义时自动被调用 深入…

Grounding DINO:开放集目标检测,将基于Transformer的检测器DINO与真值预训练相结合

文章目录 背景知识补充CLIP (Contrastive Language-Image Pre-training)&#xff1a;打破文字和图像之间的壁垒DINO(Data-INterpolating Neural Network)&#xff1a;视觉 Transformer 的自监督学习Stable Diffusion&#xff1a;从文本描述中生成详细的图像Open-set Detector开…

系列七、Spring Security中基于Jdbc的用户认证 授权

一、Spring Security中基于Jdbc的用户认证 & 授权 1.1、概述 前面的系列文章介绍了基于内存定义用户的方式&#xff0c;其实Spring Security中还提供了基于Jdbc的用户认证 & 授权&#xff0c;再说基于Jdbc的用户认证 & 授权之前&#xff0c;不得不说一下Spring Se…

【Blog】记录一下如何让自己的自建网站让百度搜索收录

记录一下如何让自己的自建网站让百度搜索收录 目录 记录一下如何让自己的自建网站让百度搜索收录一、前言二、开始操作1、第一步&#xff1a;进入设置2、第二步&#xff1a;开始设置3、第三步&#xff1a;让百度收录我们自己的文章 三、知识点记录1、注意事项2、可能会出现的问…

暄桐写字计划 | 开始布局我们的2024

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。      暄桐林曦老师有…

Kafka的安装、管理和配置

Kafka的安装、管理和配置 1.Kafka安装 官网: https://kafka.apache.org/downloads 下载安装包,我这里下载的是https://archive.apache.org/dist/kafka/3.3.1/kafka_2.13-3.3.1.tgz Kafka是Java生态圈下的一员&#xff0c;用Scala编写&#xff0c;运行在Java虚拟机上&#xf…

ENNOID-BMS从控板分析-基于LTC6813的版本

LTC6813简单说明 单体电压采集部分&#xff0c;总共可以采集18个电芯电压&#xff0c;这18个电压分别交给3个16位Delta-Sigma ADC来进行采样&#xff1b;官方手册宣称的采样误差低于2.2mV&#xff0c;采样范围为0~5V&#xff0c;所有18个电芯采样一次只要290uS时间。电压均衡部…

C++学习笔记——友元、嵌套类、异常

目录 一、友元 一个使用友元的示例代码 输出结果 二、嵌套类 一个使用嵌套类的示例代码 输出结果 三、异常 一个使用异常处理的示例代码 输出结果 四、结论 五、使用它们的注意事项 上一篇文章链接&#xff1a; C中的继承和模板是非常强大和灵活的特性&#xff0c;它…

跟着cherno手搓游戏引擎【5】layer(层)、Glad

编写基类层&#xff1a; Layer.h:提供Attach链接、Detach解绑、Update刷新、Event事件、GetName方法 #pragma once #include"YOTO/Core.h" #include"YOTO/Event/Event.h" namespace YOTO {class YOTO_API Layer{public:Layer(const std::string& nam…

【c/python】用GTK实现一个带菜单的窗口

一、用python 在GTK中创建一个带菜单的窗口&#xff0c;可以通过使用Gtk.MenuBar、Gtk.Menu和Gtk.MenuItem组件来构建菜单。以下是一个基本的例子&#xff0c;展示了如何使用Python的PyGObject库创建一个简单的带菜单栏的GTK窗口。 import gi gi.require_version(Gtk, 3.0) f…

在CMake中自定义宏 add_definitions(-DDEBUG)

hehedalinux:~/Linux/loveDBTeacher-v6$ tree . ├── CMakeLists.txt └── test.c0 directories, 2 files hehedalinux:~/Linux/loveDBTeacher-v6$ test.c #include <stdio.h> #define NUMBER 3int main() {int a 10; #ifdef DEBUGprintf("我是一个程序猿,我…

物联网介绍

阅读引言&#xff1a; 本文从多方面叙述物联网的定义以及在物联网当中的各种通信的介绍。 一、物联网的定义 1.1 通用的定义 物联网&#xff08;Internet of Things&#xff0c;IOT&#xff1b;也称为Web of Things&#xff09;是指通过各种信息传感设 备&#xff0c;如传感器、…

docker 安装redis (亲测有效)

目录 1 安装 1 安装 1 将redis 的 tar 包 上传到服务器 上传之后tar 包&#xff0c;将他变成镜像 输入docker images,发现目前是没有镜像的&#xff0c;现在将tar 包变成镜像 docker load -i redis.tar以上就将tar 包变成镜像了 现在在宿主机找一个地方&#xff0c;存放数据…

【Maven】003-基于 IDEA 创建 Maven 工程

【Maven】003-基于 IDEA 创建 Maven 工程 文章目录 【Maven】003-基于 IDEA 创建 Maven 工程一、关于 Maven 工程的 GAVP1、GAVP 简介2、GAV 坐标规范3、Packaging 定义规则 二、基于 IDEA 创建 Maven 工程1、创建 Maven 项目2、创建结果3、项目结构说明 一、关于 Maven 工程的…

机器人技能学习-构建自己的数据集并进行训练

概要 若想训练自己的场景&#xff0c;数据集的重要性不做过多赘述&#xff0c;下面就基于 robomimic 和 robosuite 构建自己的数据集进行讲解&#xff0c;同时&#xff0c;也会附上 train 和 run 的流程&#xff0c;这样&#xff0c;就形成了闭环。 自建数据集 采集数据 采…