Java笔记_20(多线程JUC)

news2025/3/1 14:26:54

一、多线程

1.1、多线程概述

进程

  • 进程是程序的基本执行实体

线程

  • 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
  • 简单理解:应用软件中互相独立,可以同时运行的功能

什么是多线程?

  • 有了多线程,我们就可以让程序同时做多件事情

多线程的作用?

  • 提高效率

多线程的应用场景?

  • 只要你想让多个事情同时运行就需要用到多线程
    比如∶软件中的耗时操作、所有的聊天软件、所有的服务器

1.2、并发和并行

并发: 在同一时刻,有多个指令在单个CPU上交替执行
并行: 在同一时刻,有多个指令在多个CPU上同时执行

1.3、多线程的实现方式

  1. 继承Thread类的方式进行实现
    1. 自己定义一个类继承Thread
    2. 重写run方法
    3. 创建子类的对象,并启动线程
      • 使用start方法
package thread;

public class Dome1 {
    public static void main(String[] args) {
        thread1 t1 = new thread1();
        thread1 t2 = new thread1();

        t1.setName("线程一");
        t2.setName("线程二");
        //线程一和线程二会同时执行
        t1.start();
        t2.start();
    }
}
package thread;

public class thread1 extends Thread {
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() +"你好啊");
        }
    }
}
  1. 实现Runnable接口的方式进行实现
    1. 在自己定义的类中接上Runnable接口
    2. 重写里面的run方法创建自己的类的对象
      • 在自己创建的类中使用 Thread.currentThread()方法可以获取到当前线程的对象
    3. 创建一个Thread类的对象,并开启线程
    4. 测试类中将自己创建的类传入到Thread类中
package thread;

public class Dome2 {
    public static void main(String[] args) {
        //创建第一个线程
        thread2 t1 = new thread2();
        Thread tt1 = new Thread(t1);
        tt1.setName("线程一");
        tt1.start();
        //创建第二个线程
        thread2 t2 = new thread2();
        Thread tt2 = new Thread(t2);
        tt2.setName("线程二");
        tt2.start();
    }
}
package thread;

public class thread2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //获取到当前线程的对象
            /*
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+"hello world");
            */
            //第二种获取对象的方式
            System.out.println(Thread.currentThread().getName()+"hello world");
        }
    }
}

  1. 利用Callable接口Future接口方式实现
    特点: 可以获取到多线程运行的结果
    1. 创建一个类MyCallable实现callable接口
    2. 重写call(是有返回值的,表示多线程运行的结果)
    3. 创建Mycallable的对象(表示多线程要执行的任务)
    4. 创建FutureTask的对象(作用管理多线程运行的结果)
    5. 创建Thread类的对象,并启动(表示线程)
package thread;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Dome3 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建thread3对象
        thread3 t1 = new thread3();
        //创建FutureTask对象(管理多线程的结果)
        FutureTask<Integer> ft = new FutureTask<>(t1);
        Thread tt1 = new Thread(ft);
        tt1.start();

        //获取多线程运行的结果
        Integer integer = ft.get();
        System.out.println(integer);
    }
}
package thread;

import java.util.concurrent.Callable;

public class thread3 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int num = 0;
        for (int i = 0; i <= 100; i++) {
            num = num+i;
        }
        return num;
    }
}

在这里插入图片描述

1.4、多线程中常见的成员方法

方法名称说明
String getName()返口此线程的名称
void setName(String name)设置线程的名字(构造方法也可以设置名字)
static Thread currentThread()获取当前线程的对象
static void sleep( long time)让线程休眠指定的时间,单位为毫秒
setPriority( int newPriority)设置线程的优先级
final int getPriority()获取线程的优先级
final void setDaemon( boolean on)设置为守护线程
public static void yield()出让线程/礼让线程
public static void join()插入线程/插队线程
  • getName()细节
    • 如果我们没有给线程设置名字,线程也是有默认的名字的
    • 格式: Thread-X(X序号,从0开始的)
    • 如果我们要给线程设置名字,可以用set方法进行设置,也可以构造方法设置
  • currentThread() 细节
    • 当JVM虚拟机启动之后,会自动的启动多条线程其中有一条线程就叫做main线程
    • 他的作用就是去调用main方法,并执行里面的代码
    • 在以前,我们写的所有的代码,其实都是运行在main线程当中
  • sleep( long time)细节
    • 哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间
    • 方法的参数:就表示睡眠的时间,单位毫秒
    • 当时间到了之后,线程会自动的醒来,继续执行下面的其他代码
package thread;

public class Dome4 {
    public static void main(String[] args) throws InterruptedException {
        //可以在类中重写构造方法来实现给多线程赋值
        
        thread4 tr1 = new thread4("aaa");
        thread4 tr2 = new thread4("bbb");

        Thread tt1 = new Thread(tr1);
        Thread tt2 = new Thread(tr2);

        tt1.start();
        tt2.start();
     
        System.out.println(Thread.currentThread().getName());//main

        System.out.println("asaaaaaaaaaaaaaaaaaaaaaa");
        //可以时jvm机睡眠 n毫秒
        Thread.sleep(5000);
        System.out.println("bbbbbbbbbbbbbbbbbbbbbbbb");
        Thread.sleep(5000);
        System.out.println("dddddddddddddddddddddddd");


    }
}

方法名称说明
setPriority( int newPriority)设置线程的优先级
final int getPriority()获取线程的优先级
  • 线程的优先级默认是5(包括main线程)
  • 改变了优先级只是先执行的概率变高了,并不是绝对先执行
package thread;

public class Dome5 {
    public static void main(String[] args) {
         thread2 t1 = new thread2();
         thread2 t2 = new thread2();

         Thread tt1 = new Thread(t1);
         Thread tt2 = new Thread(t2);

         tt1.setName("aaaa");
         tt2.setName("bbbb");
        //System.out.println(tt1.getPriority());//5
        //System.out.println(tt2.getPriority());//5

        //改变了优先级只是先执行的概率变高了,并不是绝对先执行
        tt1.setPriority(1);
        tt2.setPriority(10);

        tt1.start();
        tt2.start();
    }
}
package thread;

public class thread2 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //获取到当前线程的对象
            /*
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+"hello world");
            */
            //第二种获取对象的方式
            System.out.println(Thread.currentThread().getName()+"hello world");
        }
    }
}

方法名称说明
final void setDaemon( boolean on)设置为守护线程
  • 当其他的非守护线程执行完毕之后,守护线程会陆续结束
  • 通俗易懂:当女神线程结束了,那么备胎也没有存在的必要了
package thread;

public class Dome6 {
    public static void main(String[] args) {
        thread1 t1 = new thread1();
        thread1_1 t2 = new thread1_1();

        Thread t11 = new Thread(t1);
        Thread t22 = new Thread(t2);

        t22.setDaemon(true);//创建一个守护线程,当t11执行完毕时t22也会陆续结束

        t11.start();
        t22.start();
    }
}
package thread;

public class thread1 extends Thread {
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() +"你好啊");
        }
    }
}
package thread;

public class thread1_1 extends Thread{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() +"你不好吗");
        }
    }
}
方法名称说明
public static void yield()出让线程/礼让线程
public static void join()插入线程/插队线程
  • 尽可能地让结果均匀,由于是让出当前CPU的执行权,多线程再次抢夺执行权时,同样可能再次被原来线程抢夺到
package thread;

public class Dome7 {
    public static void main(String[] args) {
        thread5 t1 = new thread5();
        thread5 t2 = new thread5();

        Thread tt1 = new Thread(t1);
        Thread tt2 = new Thread(t2);

        tt1.start();
        tt2.start();
    }
}
package thread;

public class thread5 extends Thread {
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() +"你不好吗");
        }
        //表示让出当前CPU的执行权
        Thread.yield();
    }
}

方法名称说明
public static void join()插入线程/插队线程
package thread;

public class Dome8 {
    public static void main(String[] args) throws InterruptedException {
        thread1 t = new thread1();
        Thread t1 = new Thread(t);

        t1.start();
        //表示把t这个线程,插入到当前线程之前。
        //当前线程:main线程
        t1.join();
        /*
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        Thread-0你好啊
        你好
        你好
        你好
        你好
        你好
        * */
        //当前执行在mian线程下
        for (int i = 0; i < 5; i++) {
            System.out.println("你好");
        }
    }
}
package thread;

public class thread1_1 extends Thread{
    @Override
    public void run() {
        //书写线程要执行的代码
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() +"你不好吗");
        }
    }
}

1.5、线程的生命周期

在这里插入图片描述

  • sleep()方法执行结束之后会编程就绪状态

1.6、线程安全的问题

把操作共享数据的代码锁起来

格式:

synchronized(){
	操作共享数据的代码
}

特点1: 锁默认打开,有一个线程进去了,锁自动关闭
特点2: 里面的代码全部执行完毕,线程出来,锁自动打开

  • 细节:
    • synchronized锁的代码必须在循坏外面,否则会导致一个线程执行完所有的代码
    • synchronized锁对象一定要是唯一的,一般使用当前类的字节码文件:类.class

如果没有代码会出现的问题:

  1. 静态变量会发生重复
  2. 静态变量会超出方法里给限定的范围
  • 问题原因:
    • 线程执行时,会有随机性
package threadTest;

public class test1 {
    public static void main(String[] args) {
        test1_thead t1 = new test1_thead();
        test1_thead t2 = new test1_thead();
        test1_thead t3 = new test1_thead();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}
package threadTest;

public class test1_thead extends Thread{
    static int ticket = 0;

    static Object obj = new Object();
    @Override
    public void run() {

            while (true){
                synchronized(test1_thead.class){
                if (ticket<100){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    ticket++;
                    System.out.println(getName()+"正在销售第"+ticket+"张票");
                }else {
                    break;
                }
            }
        }

    }
}

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

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

相关文章

SpringBoot整合JPA

JPA、Hibernate、Spring Data JPA的关系 JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。Sun引入新的JPA ORM规范出于两个原因&…

从零入门激光SLAM(九)——三维点云基础

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。随着知识的越来越多&#xff0c;越来越细&#xff0c;我准备整理一个自己的激光SLAM学习笔记专栏&#xff0c;从0带大家快速上手激…

新品发布全线添员,九号全力奔向“红海”深处?

5月10日&#xff0c;九号公司2023新品发布会声势达到顶峰。此次发布会的看点为九号电动2023产品线的更新&#xff0c;电动家族再添多员大将。 随着人们出行选择的多样化&#xff0c;国内短途出行工具发展迎来井喷期。在传统的电动两轮车市场上&#xff0c;雅迪、爱玛等品牌仍然…

基于java(springboot)和go-cqhttp实现QQ机器人

目录 yh-qqrobot机器人简介go-cqhttp搭建1.下载应用2.生成bat文件3. 初始化项目4. 配置5. 运行项目 yh-qqrobot搭建搭建后端1. 导入sql文件2. 配置文件3. 导入到idea 搭建前端 yh-qqrobot机器人简介 yh-qqrobot是一个基于若依框和go-cqhttp集成的系统&#xff0c;一开始我只是揣…

生成一个简版导游地图

目录 1 简版导游地图功能简介 2 注册并登录 3 设置景区&#xff08;商圈&#xff09;地图 3.1 新增景区 3.2 增加一个景点介绍 3.3 地图中增加一个景点 3.4 增加几个其他类型的点&#xff0c;如“美食”、“购物”、“停车” 4 申请审核 5 欣赏一下 1 简版导游地图功能…

【python 异常处理】零基础也能轻松掌握的学习路线与参考资料

Python 异常处理是编写高质量、功能稳定程序的关键之一&#xff0c;它可以帮助开发者优化程序的稳定性和可读性&#xff0c;更好地管理代码的错误和异常情况。 本文将介绍 Python 异常处理的学习路线、参考资料和优秀实践&#xff0c;以帮助 Python 开发者提高应对程序中错误和…

华为OD机试真题 Java 实现【微服务的集成测试】【2023Q1 100分】

一、题目描述 现在有n个容器服务&#xff0c;服务的启动可能有一定的依赖性&#xff08;有些服务启动没有依赖&#xff09;&#xff0c;其次服务自身启动加载会消耗一些时间。 给你一个 nxn 的二维矩阵 useTime&#xff0c;其中 useTime[i][i]10 表示服务 i 自身启动加载需要消…

十大排序算法

1.冒泡排序 步骤:从头元素开始比较每一对相邻元素&#xff0c;如果第1个比第2个大&#xff0c;就交换它们的位置&#xff0c;执行完一轮&#xff0c;最末尾的那个元素就是最大的元素 1.1冒泡算法 void BubbleSort(int arr[], size_t length) {for (int end length-1; end &…

.netcore3.1+jenkins+Docker

一.git安装 1.下载 https://github.com/git/git/releases/tag/v2.40.1 2.将本地的安装包上传到 linux 服务器上&#xff0c;我这里放在 /opt/git/ 目录下 3.解压压缩包&#xff0c;得到目录 git-2.40.1&#xff0c;位置在 /opt/git/git-2.40.1 tar -zxvf git-2.40.1.tar.gz 4.…

AIGC产业研究报告2023——视频生成篇

易观&#xff1a;今年以来&#xff0c;随着人工智能技术不断实现突破迭代&#xff0c;生成式AI的话题多次成为热门&#xff0c;而人工智能内容生成&#xff08;AIGC&#xff09;的产业发展、市场反应与相应监管要求也受到了广泛关注。为了更好地探寻其在各行业落地应用的可行性…

【1++的C++初阶】之类与对象

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C初阶】 文章目录 一&#xff0c;面向对象与面向过程二&#xff0c;类2.1 类的定义2.2 类的访问限定符2.3 封装2.3.1 什么是封装2.3.2 封装的作用 2.4 类与对象 三&#xff0c;this指针3.1 什…

Docker 应用部署-MySQL

一、安装MySQL 1搜索mysql镜像 docker search mysql 2拉取mysql镜像 docker pull mysql:8.0.20 3创建容器 通过下面的命令&#xff0c;创建容器并设置端口映射、目录映射 #在用户名目录下创建mysql目录用于存储mysql数据信息 mkdir /home/mysql cd /home/mysql #创建docker容…

【数据结构】[LeetCode138. 复制带随机指针的链表]

一.问题描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值…

5。STM32裸机开发(1)

嵌入式软件开发学习过程记录&#xff0c;本部分结合本人的学习经验撰写&#xff0c;系统描述各类基础例程的程序撰写逻辑。构建裸机开发的思维&#xff0c;为RTOS做铺垫&#xff08;本部分基于库函数版实现&#xff09;&#xff0c;如有不足之处&#xff0c;敬请批评指正。 &a…

ssm框架之SpringMVC:域共享数据

本篇主要聊的是在springmvc中的共享域传递数据的使用。如果对共享域可能不了解的话&#xff0c;可以看下前面聊servlet的时候&#xff0c;对共享域的详细描述&#xff0c;以及其作用和方法。传送阵 至于如何构建SpringMVC的环境&#xff0c;以及如何构建一个项目&#xff0c;可…

一款基于 Python+flask 的态势感知系统(附完整源码)

一、开发 一个基于linux的态势感知系统&#xff0c;基于python和flask框架开发&#xff0c;项目文件目录如下&#xff1a; admin -核心算法 charts -图表生成 model -类 app.py -主文件 config.py -配置文件 install.py -安装文件 项目文件在文章结尾处~ 二、安装 1、…

矩池云搭建DeepLabV3Plus网络,预测无人机遥感语义分割数据集

先上效果图&#xff0c;效果是真不错呀&#xff01; 带大家复现这个过程 一、下载源码 代码下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1MkW7DOgNHD5h5sfXQ6L1HA 提取码&#xff1a;ynev 权重下载地址&#xff1a; 链接&#xff1a;https://pan.bai…

Java - 欢迎使用spring中的Base64Utils!

&#x1f335;如果项目技术栈中包含spring&#xff0c;同时又有Base64编码的需求&#xff0c;那么Base64Utils工具类将会是你的最好选择&#xff01;⤵️ 什么是Base64编码&#xff1f;⤵️ 基本转换针对URL的转换 &#xff08;/替换为-_&#xff09; Base64Utils公开的AP…

工业软件上云:有“数据之根”方能向阳生长

有人说&#xff0c;数字化时代&#xff0c;所有的事情都值得用云的方式重新做一遍。 深以为然。作为拥有全球工业门类最为齐全的国家&#xff0c;中国近年来正在从制造大国向制造强国迈进。随着《中国制造2025》国家战略的稳步推进&#xff0c;制造业的数字化转型和智能化升级…

【倒计时2天】CCIG文档图像智能分析与处理论坛开启直播预约,共探智能文档处理前沿技术

文档是人们在日常生活、工作中产生的信息的重要载体&#xff0c;各领域从业者几乎每天都要与金融票据、商业规划、财务报表、会议记录、合同、简历、采购订单等文档“打交道”。让计算机具备阅读、理解和解释这些文档图像的能力&#xff0c;在智能金融、智能办公、电子商务等许…