多线程初阶(一)

文章目录

    • 1.线程和进程的区别
    • 2.创建线程
      • 2.1Thread类
      • 2.2Runnable接口
      • 2.3匿名类创建Thread子类对象
      • 创建后台线程
    • 3.Thread常⻅⽅法
    • 4.中断线程
      • 4.1中断标记(Interrupt Flag)
      • 4.2调⽤ interrupt() ⽅法
    • 5.线程状态

1.线程和进程的区别

1.进程中包含线程,一个进程中至少一个线程(主线程)
2.进程是申请系统资源的最小单位
3.线程是CPU调度的最小单位
4.线程之间共享进程申请的系统资源
5.一个线程崩溃,会影响整个进程

2.创建线程

2.1Thread类

 public static void main(String[] args) throws InterruptedException {
        Mythred mythred = new Mythred();
        //开启线程
        mythred.start();
        //main方法中的循环
        while (true) {
            Thread.sleep(1000);
            System.out.println("同时进行");
        }
    }

    static class Mythred extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("测试");
            }
        }
    }

在这里插入图片描述

2.2Runnable接口

public static void main(String[] args) {
        MyRunnable01 myRunnable01=new MyRunnable01();
        MyRunnable02 myRunnable02=new MyRunnable02();
        Thread thread01=new Thread(myRunnable01);
        Thread thread02=new Thread(myRunnable01);
        Thread thread03=new Thread(myRunnable02);
        thread01.start();
        thread02.start();
        thread03.start();
    }
    static class MyRunnable01 implements Runnable{
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("产生服装,金币+50");
            }
        }
    }
    static class MyRunnable02 implements Runnable{

        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("产生墨镜,金币+10");
            }
        }
    }

在这里插入图片描述

2.3匿名类创建Thread子类对象

import java.lang.invoke.LambdaConversionException;

public class test5 {
    public static void main1(String[] args) {
        Thread thread=new Thread(){
            public void run(){
                System.out.println("通过匿名内部类(Thread)实现");
            }
        };
        thread.start();
    }

    public static void main2(String[] args) {
        Thread thread=new Thread(new Runnable() {
            public void run() {
                System.out.println("通过匿名内部类(Runnable)实现");
            }
        });
        thread.start();
    }

    public static void main(String[] args) {
        Thread thread=new Thread(() ->{
            System.out.println("通过Lambda实现");
        });
        thread.start();
    }
}

在这里插入图片描述

创建后台线程

自动终止:后台线程不会阻止JVM的退出。如果所有的用户线程都结束了,JVM会自动关闭,即使后台线程仍在运行。
优先级:后台线程的优先级通常较低,但这并不是强制的。你可以通过Thread.setPriority()方法设置线程的优先级。
使用场景:后台线程通常用于执行一些辅助任务,比如垃圾回收、日志记录、监控等

在设置线程为后台线程之前,必须先调用start()方法,否则会抛出IllegalThreadStateException。
后台线程的运行时间不应过长,因为它们可能在JVM关闭时被强制终止,可能导致数据丢失或状态不一致。
不建议在后台线程中执行需要保证完成的任务,例如文件写入或数据库操作。

 Thread thread = new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("啦啦啦");
            }
        }, "这是我的名字");
        //设置为后台线程
        thread.setDaemon(true);
        System.out.println("线程是否存活:"+thread.isAlive());
        thread.start();
        System.out.println("线程是否存活:"+thread.isAlive());
        System.out.println("mian方法完成:");

在这里插入图片描述

3.Thread常⻅⽅法

在这里插入图片描述
• ID 是线程的唯⼀标识,不同线程不会重复
• 名称是各种调试⼯具⽤到
• 状态表⽰线程当前所处的⼀个情况,下⾯我们会进⼀步说明
• 优先级⾼的线程理论上来说更容易被调度到
• 关于后台线程,需要记住⼀点:JVM会在⼀个进程的所有⾮后台线程结束后,才会结束运⾏。
• 是否存活,即简单的理解,为 run ⽅法是否运⾏结束了

public static void main(String[] args) {
        Thread thread = new Thread (()->{
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("啦啦啦");
            }
        },"这是我的名字");
        thread.start();
        System.out.println("线程名称:"+thread.getName());
        System.out.println("线程序号:"+thread.getId());
        System.out.println("线程优先级:"+thread.getPriority());
        System.out.println("线程状态:"+thread.getState());
        System.out.println("线程是否存活:"+thread.isAlive());
        System.out.println("线程是否被中断:"+thread.isInterrupted());
    }

在这里插入图片描述

4.中断线程

4.1中断标记(Interrupt Flag)

使用变量去中断

 static boolean flg=false;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread (()->{
            while (!flg) {
                try {
                    System.out.println("啦啦啦");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("线程已退出");
        },"这是我的名字");
        thread.start();
        Thread.sleep(4000);
        flg=true;
    }

在这里插入图片描述

4.2调⽤ interrupt() ⽅法

public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("啦啦啦");
                try {
                    Thread.sleep(1000);//大部分时间停留在睡眠
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("休眠被中断");
                    break;
                }
                System.out.println("线程结束");
            }
        }, "这是我的名字");
        System.out.println("线程是否存活:"+thread.isAlive());
        thread.start();
        //使线程休眠会
        Thread.sleep(1000);
        System.out.println("线程是否存活:"+thread.isAlive());
        //中断线程
        thread.interrupt();
        //等待线程被销毁
        Thread.sleep(1000);
        System.out.println("线程是否存活:"+thread.isAlive());
    }

在这里插入图片描述

  public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("啦啦啦");
            }
            System.out.println("线程结束");
        }, "这是我的名字");
        System.out.println("线程是否存活:"+thread.isAlive());
        thread.start();
        System.out.println("线程是否存活:"+thread.isAlive());
        Thread.sleep(2);
        //中断线程
        thread.interrupt();
        //等待线程被销毁
        Thread.sleep(100);
        System.out.println("线程是否存活:"+thread.isAlive());
    }

在这里插入图片描述
interrupt() 标准、安全,支持阻塞状态响应 需主动检查中断标志 需协作终止的线程

volatile 标志位 简单直观 无法响应阻塞状态 无阻塞任务的线程

5.线程状态

1.NEW:表示创建好了一个java线程对象,安排好了任务,但是还没有启动,没有调用start()方法之前不创建PCB。
2.RUNNABLE:运行+就绪状态,在系统中有对应PCB
**3.BLOCKED:**等待锁的状态,阻塞中的一种
**4.WATING:**线程因为调用了Object.wait()、Thread.join()或LockSupport.park()方法而进入等待状态。线程会一直等待,直到其他线程显式地唤醒它。
**5.TIMED_WATING:**指定等待时间的阻塞状态,线程因为调用了带有超时参数的Object.wait(long)、Thread.join(long)、Thread.sleep(long)或LockSupport.parkNanos()等方法而进入计时等待状态。线程会在指定的时间后自动唤醒,或者被其他线程提前唤醒。
6.TERMINATED:结束,PCB已经被销毁,但是java线程对象还在。

public static void main(String[] args) throws InterruptedException {
        Thread  thread = new Thread (()->{
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        });
        System.out.println("线程状态"+thread.getState());
        thread.start();
        System.out.println("线程状态"+thread.getState());
        Thread.sleep(100);
        // 主线程休眠,确保子线程进入TIMED_WAITING状态
        System.out.println("线程状态"+thread.getState());
        thread.join();
        System.out.println("线程状态"+thread.getState());
    }

在这里插入图片描述

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

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

相关文章

1.3 Spring Boot原理解析

Spring Boot通过起步依赖(如spring-boot-starter-parent和spring-boot-starter-web)简化项目配置,减少版本冲突和依赖配置代码量。它采用“约定大于配置”的设计思想,通过SpringBootApplication注解(包含SpringBootCon…

⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II

⭐算法OJ⭐N-皇后问题【回溯剪枝】(C实现)N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…

第6章 定时器计数器

目录 6.1 定时计数器的结构框图 6.2 定时器的控制字 6.2.1 TMOD:工作方式控制寄存器 6.2.2 定时/计数器控制寄存器TCON 6.3 定时/计数器的4种工作方式 6.3.1 方式0、方式1(13位、16位定时计数方式) 6.3.2 方式2(常数自动重装入) 6.3.3 方…

JavaWeb基础一(Tomcat、Maven)

前言 web开发 web开发:Web开发是指在万维网或私有网络上创建和维护网站的工作。它包括网页设计、网页编程、数据库管理等多方面的技术。Web开发可以分为前端开发和后端开发,前端主要关注用户界面和用户体验,而后端则处理服务器、应用程序和…

写一写idea中使用tomcat启动activiti过程

一 环境 tomcat 9.0.62 activiti的war包版本 7.1.0.M6 二 操作 官网下载:https://www.activiti.org/get-started 2.1 先在idea中编辑配置 2.2 点击加号然后选择tomcat本地进行确认 2.3 点击部署之后下边小加号 选择第二个之后就是选择自己想要使用tomcat启动的…

基于开源库编写MQTT通讯

目录 1. MQTT是什么?2. 开发交互UI3. 服务器核心代码4. 客户端核心代码5. 消息订阅与发布6. 通讯测试7. MQTT与PLC通讯最后. 核心总结 1. MQTT是什么? MQTT(Message Queuing Terlemetry Transport)消息队列遥测协议;是…

MAVEN手动配置(阿里云)全教程

介于网上各种各样的MAVEN配置过程中方法大致相同却细节参差不齐,我总结了我遇见的一些问题,来完全的解决MAVEN手动配置的全过程,以及分享解决小毛病的经验。 所需材料: MAVEN3.9.9(下载适合自己的版本即可&#xff09…

从0到1入门Linux

一、常用命令 ls 列出目录内容 cd切换目录mkdir创建新目录rm删除文件或目录cp复制文件或目录mv移动或重命名文件和目录cat查看文件内容grep在文件中查找指定字符串ps查看当前进程状态top查看内存kill终止进程df -h查看磁盘空间存储情况iotop -o直接查看比较高的磁盘读写程序up…

pytest结合allure

Allure 一、文档二、指令三、装饰器3.1 allure.step装饰器3.2 allure.description装饰器3.3 allure.title装饰器3.4 allure.link、allure.issue 和 allure.testcase装饰器3.5 allure.epic、allure.feature 和 allure.story装饰器3.6 allure.severity装饰器 一、文档 allure文档…

Dockerfile 深入浅出:从基础到进阶全解析

Dockerfile 深入浅出:从基础到进阶全解析 各位同学,大家好!欢迎来到今天的 Dockerfile 课程。Docker 技术在当今的软件开发和部署领域可以说是非常热门,而 Dockerfile 作为构建 Docker 镜像的关键文件,掌握它对于我们…

大模型巅峰对决:DeepSeek vs GPT-4/Claude/PaLM-2 全面对比与核心差异揭秘

文章目录 一、架构设计深度解剖1.1 核心架构对比图谱1.2 动态MoE架构实现架构差异分析表 二、训练策略全面对比2.1 训练数据工程对比2.2 分布式训练代码对比DeepSeek混合并行实现GPT-4 Megatron实现对比 2.3 关键训练参数对比 三、性能表现多维评测3.1 基准测试全景对比3.2 推理…

贪心算法二

> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是贪心算法,并且掌握贪心算法。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! >…

【Mac】MacOS系统下常用的开发环境配置2025版

早期版本的一个环境搭建参考 1、brew Mac自带终端运行: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" Installation successful!成功后运行三行命令后更新环境(xxx是mac的username&a…

【JavaEE】SpringMVC简单练习

目录 一、计算器1.1 接口定义1.2 前端代码1.3 后端代码1.4 运行结果 二、⽤⼾登录2.1 需求2.2 接口定义2.3 前端页面2.4 后端代码2.5 结果 三、留⾔板3.1 需求:3.2 接口3.3 前端代码3.4 后端代码3.5 运行结果 四、图书管理系统4.1 需求4.2 接口定义4.3 后端代码 一、计算器 1.…

go 分布式redis锁的实现方式

go 语言以高并发著称。那么在实际的项目中 经常会用到锁的情况。比如说秒杀抢购等等场景。下面主要介绍 redis 布式锁实现的两种高并发抢购场景。其实 高并发 和 分布式锁 是一个互斥的两个状态: 方式一 setNX: 使用 redis自带的API setNX 来实现。能解决…

网络安全等级保护2.0 vs GDPR vs NIST 2.0:全方位对比解析

在网络安全日益重要的今天,各国纷纷出台相关政策法规,以加强信息安全保护。本文将对比我国网络安全等级保护2.0、欧盟的GDPR以及美国的NIST 2.0,分析它们各自的特点及差异。 网络安全等级保护2.0 网络安全等级保护2.0是我国信息安全领域的一…

upload-labs靶场 1-21通关

目录 1.Pass-01 前端绕过 分析 解题 2.Pass-02 服务器端检测--修改IMME 分析 解题 3.Pass-03 黑名单绕过 分析 解题 4.Pass-04 .htaccess绕过 分析 解题 5.Pass-05 . .绕过和.user.ini绕过 分析 解题 6.Pass-06 大小写绕过 分析 解题 7.Pass-07 空格绕过 分…

CInternetToolbar::_CommonHandleFileSysChange函数分析之CReBar::_IDToIndex函数的作用

第一部分: // IMPORTANT: dont change the value of anything between CBIDX_FIRST and CBIDX_LAST. // CInternetToolbar::_LoadUpgradeSettings assumes these values havent changed from // version to version. #define CBIDX_MENU 1 …

为AI聊天工具添加一个知识系统 之138 设计重审 之2 文章学 引言之2 附加符号学附属诠释学附随工程学(联系)

本文要点 要点 符号学大局观: 诠释学(当代 加成[0]:“预期”和“预设” 两者的 不期而遇 。“邂逅”) 我们在文章学工具设计中 以全局观考虑:嵌入编程工具的逻辑性底( 哲学诠释 下确界) 并…

VEC系列-RabbitMQ 入门笔记

消息队列(MQ)对于开发者来说是一个经常听到的词汇,但在实际开发中,大多数人并不会真正用到它。网上已经有很多关于 MQ 概述和原理的详细讲解,官网文档和技术博客也都介绍得很深入,因此,我在这里…