当前位置: 首页 > news >正文

【JavaSE线程知识总结】

多线程

  • 一.创建线程
    • 1.多线程创建方式一(Thread)
    • 2.多线程创键方式二(Runnable)
    • 3.线程创建方式三
  • 二.线程安全问题
    • 解决办法
      • 1.使用同步代码块synchornized
    • 2 .使用Lock解决线程安全问题
  • 三.总结

  • 线程就是程序内部的一条执行流程

一.创建线程

常用的方法

  • Thread.currentThread(): 获取当前线程
  • Thread.getName(): 获取当前线程的名称
  • Thread.setName(): 设置当前线程的名称
  • Thread.yield(): 礼让当前正在执行的线程
  • Thread.sleep(long millis): 让当前线程暂停millis毫秒
  • Thread.interrupt(): 中断当前线程
  • Thread.isInterrupted(): 判断当前线程是否被中断
  • Thread.currentThread().interrupt(): 中断当前线程
  • Thread.join(): 插队,调用这个方法的线程先执行完毕
  • Thread.sleep()睡眠

1.多线程创建方式一(Thread)

  • 定义一个子类MyThread继承Thread,重写run方法
  • 创建Mythread类的对象
  • 通过对象调用start方法启动线程,线程开启后,会自动调用线程对象的run方法执行
  • JVM会自动开启一个线程,执行main方法,称为主线程
  • 主线程中开启了其他线程称为子线程
  • 开启了子线程后,子线程会跟我们的主线程争抢资源,谁抢到了谁就先执行,执行一小会用释放,再重新抢占资源
    优点: 创建线程简单
    缺点: 扩展性不强,不能返回线程执行结果
    在这里插入图片描述
    在这里插入图片描述

2.多线程创键方式二(Runnable)

  • 定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法
  • 创建MyRunnable任务对象
  • 把MyRunnable对象交给Thread处理
  • 调用start()方法启动线程

优点
线程任务与线程对象分离,可以让同一线程执行不同的任务
缺点
需要多一个Runnable对象
不能返回线程结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.线程创建方式三

  • 实现callable<返回值类型>接口,重写call方法
  • callable接口在实现的时候需要指定泛型,用来确定返回值的数据类型
  • 创建FutureTask对象,构造方法中需要传入callable接口实现类对象
  • FutureTask()中提供了一个get(),它是一个阻塞的方法,他会阻塞线程一直从Futurue对象中去获取返回的结果,如果没有获取到会一致阻塞等待
  • 创建Thread对象,构造方法中传入futureTask对象
  • 调用start()方法启动线程
  • 调用get()方法的时候会有异常(最好分开进行try… catch异常捕获,因为当有一条线程出现异常的时候,不会影响到其他线程的返回结果,)
package com.dream.Thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class ThreadDemo03 {public static void main(String[] args) {//1.线程创建的方式三: 实现callable接口,重写call方法//callable接口在实现的时候需要指定泛型,用来确定返回值的数据类型//2.创建callable接口实现类的对象MyThread3 myThread3 = new MyThread3(100);//3.创建FutureTask对象,构造方法中需要传入callable接口实现类对象FutureTask<String> futureTask = new FutureTask<>(myThread3);//futureTask对象是线程任务对象,他的get方法可以在线程运行结束后,获取线程执行结果//4.创建Thread对象,构造方法中传入futureTask对象Thread t = new Thread(futureTask);//5.启动线程t.start();MyThread3 myThread3_2 = new MyThread3(200);FutureTask<String> futureTask_2 = new FutureTask<>(myThread3_2);Thread t2 = new Thread(futureTask_2);t2.start();//6.获取线程执行结果(最好分开进行try... catch异常捕获,因为当有一条线程出现异常的时候,不会影响到其他线程的返回结果,)try {String result = futureTask.get();System.out.println(result);} catch (Exception e) {e.printStackTrace();}try {String result_2 = futureTask_2.get();System.out.println(result_2);} catch (Exception e) {e.printStackTrace();}}
}class MyThread3 implements Callable<String> {private int n;public MyThread3(int n) {this.n = n;}@Overridepublic String call() throws Exception {//计算1-n的和返回int sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return "1-" + n + "的和为:" + sum;}
}

二.线程安全问题

  • 存在多个线程在同时执行
  • 同时访问一个共享资源
  • 同时对共享资源做操作

比如两个人访问同一个银行账户,就会出现线程安全问题

package com.dream.threadsafe;public class MyRunnable implements Runnable {private Account account = new Account();@Overridepublic void run() {if (account.getBalance() >= 100000) {account.withdraw(account, 100000);} else {System.out.println("余额不足,取款失败");}}
}/*** 模拟取款*/class Account {private int balance = 100000;// 余额public int getBalance() {return balance;}public void withdraw(Account acc, int amount) {System.out.println(Thread.currentThread().getName() + "正在取款" + amount);balance -= amount;System.out.println(Thread.currentThread().getName() + "取款成功,余额为" + balance);}
}

启动线程

public class Test {public static void main(String[] args) {MyRunnable mr = new MyRunnable();Thread t1 = new Thread(mr, "小明");Thread t2 = new Thread(mr, "小红");t1.start();t2.start();}
}

解决办法

1.使用同步代码块synchornized

  • 同步锁:我们传入的参数要是唯一的对象,
  • 但是不要直接使用字符串作为锁对象,因为会导致其它无关线程不能同步线程
  • 如果同步锁对象是在实例方法内部,那么锁对象就是this
  • 每次抢占到资源都会判断当前锁是否是开启的,开启了就进入执行,关闭则等待
  • 如果同步锁对象是在静态方法内部,那么锁对象就是 类名.class
  • 也可以直接加在方法的修饰符后面,构成同步方法
    在这里插入图片描述
    在这里插入图片描述

2 .使用Lock解决线程安全问题

  • Lock是一个接口,需要创建它的实现类对象ReentranLock()是Lock接口的实现类
  • 相较于synchronized锁,Lock会更加的灵活
  • 他俩都属于重量级锁
private final Lock lk = new ReentrantLock();
public void withdraw(Account acc, double money) {lk.lock();//上锁try {if (this.money >= money) {//余额足够,取款System.out.println(Thread.currentThread().getName() + "取款成功");//更新余额this.money -= money; //System.out.println(acc.getCardId() + "余额为:" + this.money);} else {System.out.println("余额不足");System.out.println(Thread.currentThread().getName() + "取款失败");}} finally {lk.unlock();//解锁}}

三.总结

本章主要讲解了线程几种线程的创建方式,线程安全问题出现的场景,以及线程安全的解决方式

相关文章:

【JavaSE线程知识总结】

多线程 一.创建线程1.多线程创建方式一(Thread)2.多线程创键方式二(Runnable)3.线程创建方式三 二.线程安全问题解决办法1.使用同步代码块synchornized 2 .使用Lock解决线程安全问题 三.总结 线程就是程序内部的一条执行流程 一.创建线程 常用的方法 Thread.currentThread()…...

FreeRTOS内存管理

1. 为什么要自己实现内存管理 对于内核对象&#xff0c;可以使用时分配&#xff0c;不使用时释放C语音的库函数不适应与FreeRTOS: 实现过于复杂&#xff0c;占用空间大并非线程安全的运行不确定性&#xff1a;每次运算时间不确定内存碎片化不太编译器配置不同调试难 2. 堆栈…...

利用服务工作线程serviceWorker缓存静态文件css,html,js,图片等的方法,以及更新和删除及版本控制

Service Worker 是一种运行在浏览器背后的独立线程&#xff0c;可以用来处理推送通知、后台同步、缓存等任务。以下是使用 Service Worker 来缓存图片的一个基本示例&#xff1a; 1、注册 Service Worker: 首先&#xff0c;你需要在你的 JavaScript 文件中注册 Service Worker。…...

MuMu模拟器安卓12安装Xposed 框架

MuMu模拟器安卓12安装Xposed 框架 当开启代理后,客户端会对代理服务器证书与自身内置证书展开检测,只要检测出两者存在不一致的情况,客户端就会拒绝连接。正是这个原因,才致使我们既没有网络,又抓不到数据包。 解决方式: 通过xposed框架和trustmealready禁掉app里面校验…...

高级数据结构——hash表与布隆过滤器

文章目录 hash表与布隆过滤器1. hash函数2. 选择hash函数3. 散列冲突3.1 负载因子3.2 冲突解决3. STL中的散列表 4. 布隆过滤器4.1 背景1. 应用场景2. 常见的处理场景&#xff1a; 4.2 布隆过滤器构成4.3 原理4.4 应用分析4.5 要点 5. 分布式一致性hash5.1 缓存失效问题 6. 大数…...

【网络】什么是交换机?switch

交换机&#xff08;Switch&#xff09;意为“开关”&#xff0c;是一种用于电&#xff08;光&#xff09;信号转发的网络设备。以下是关于交换机的详细解释&#xff1a; 一、交换机的基本定义 功能&#xff1a;交换机能为接入交换机的任意两个网络节点提供独享的电信号通路&am…...

软件测试 —— 自动化基础

目录 前言 一、Web 自动化测试 1.什么是 Web 自动化测试 2.驱动 3.安装驱动管理 二、Selenium 1.简单 web 自动化测试示例 2.工作原理 三、元素定位 1.cssSelector 2.XPath 四、操作测试对象 1.点击/提交对象 2.模拟按键输入 3.清除文本内容 4.获取文本信息 5.…...

深入解析 OpenHarmony 构建系统-4-OHOSLoader类

在OpenHarmony操作系统构建过程中&#xff0c;OHOSLoader类扮演着至关重要的角色。这个类负责加载和解析构建配置&#xff0c;生成必要的构建文件&#xff0c;并确保构建过程的顺利进行。本文将深入分析OHOSLoader类的实现细节&#xff0c;揭示其如何管理构建配置&#xff0c;并…...

【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构

Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…...

排序算法(基础)大全

一、排序算法的作用&#xff1a; 排序算法的主要作用是将一组数据按照特定的顺序进行排列&#xff0c;使得数据更加有序和有组织。 1. 查找效率&#xff1a;通过将数据进行排序&#xff0c;可以提高查找算法的效率。在有序的数据中&#xff0c;可以使用更加高效的查找算法&…...

Pytest从入门到精通

一、pytest单元测试框架 (1)什么是单元测试框架 单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查测试。 (2)单元测试框架 java : junit和testng python : unittest和pytest (3)单元测试框架主要做什么? 1.测试发现:从多个文件里面去找到我们测试…...

《C++ 实现生成多个弹窗程序》

《C 实现生成多个弹窗程序》 在 C 编程中&#xff0c;我们可以利用特定的系统函数来创建弹窗&#xff0c;实现向用户展示信息等功能。当需要生成多个弹窗时&#xff0c;我们可以通过循环结构等方式来达成这一目的。 一、所需头文件及函数介绍 在 Windows 操作系统环境下&#…...

react 中 useRef Hook 作用

useRef是一个非常实用的钩子函数 一、访问和操作 DOM 元素 1. 获取 DOM 元素引用 1.1 基本原理 通过 useRef 我们可以直接操作 DOM 元素 1.2 代码示例 import React, { useRef, useEffect } from "react";const InputFocusComponent () > {const inputRef …...

Scala-键盘输入(StdIn)-用法详解

Scala 在 Scala 中&#xff0c;进行 键盘输入 主要通过 scala.io.StdIn 包来实现。 StdIn 提供了几个方法&#xff0c;用于从用户的键盘输入中读取不同类型的数据&#xff0c;如字符串、整数、浮点数等。 常用的输入方法有 readLine()、readInt()、readDouble()、readShort(…...

力扣(LeetCode)283. 移动零(Java)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:Java入门知识&#x1f649; &#x1f439;今日诗词:雾失楼台&#xff0c;月迷津渡&#x1f439; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主&#x1f64f; ⛳️点赞 ☀️收藏⭐️关注&#x1f4ac;卑微小博主…...

ESP32C3单片机使用笔记---烧录MicroPython

使用MicroPython在ESP32C3单片机上编程&#xff0c;首先需要将MicroPython运行环境烧录到ESP32C3的Flash中去&#xff0c;步骤如下&#xff1a; 1.下载esptool烧录工具&#xff0c;下载地址&#xff1a; https://github.com/espressif/esptool 直接使用git clone git clone…...

Matter1.4重磅来袭,智能家居进入“互联”新纪元

近日&#xff0c;连接标准联盟&#xff08;CSA&#xff09;正式宣布推出最新的Matter1.4标准版本&#xff0c;并更新了一系列“史诗级”的增强功能&#xff0c;旨在提升现有智能家居之间的互操作性与兼容性&#xff0c;为智能家居用户带来更流畅的使用体验。 华普微&#xff0c…...

tdengine学习笔记

官方文档&#xff1a;用 Docker 快速体验 TDengine | TDengine 文档 | 涛思数据 整体架构 TDENGINE是分布式&#xff0c;高可靠&#xff0c;支持水平扩展的架构设计 TDengine分布式架构的逻辑结构图如下 一个完整的 TDengine 系统是运行在一到多个物理节点上的&#xff0c;包含…...

机器学习-36-对ML的思考之机器学习研究的初衷及科学研究的期望

文章目录 1 机器学习最初的样子1.1 知识工程诞生(专家系统)1.2 知识工程高潮期1.3 专家系统的瓶颈(知识获取)1.4 机器学习研究的初衷2 科学研究对机器学习的期望2.1 面向科学研究的机器学习轮廓2.2 机器学习及其应用研讨会2.3 智能信息处理系列研讨会2.4 机器学习对科学研究的重…...

Linux 进程信号的产生

目录 0.前言 1. 通过终端按键产生信号 1.1 CtrlC&#xff1a;发送 SIGINT 信号 1.2 Ctrl\&#xff1a;发送 SIGQUIT 信号 1.3 CtrlZ&#xff1a;发送 SIGTSTP 信号 2.调用系统命令向进程发信号 3.使用函数产生信号 3.1 kill 函数 3.2 raise 函数 3.3 abort 函数 4.由软件条件产…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

手动给中文分词和 直接用神经网络RNN做有什么区别

手动分词和基于神经网络&#xff08;如 RNN&#xff09;的自动分词在原理、实现方式和效果上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 实现原理对比 对比维度手动分词&#xff08;规则 / 词典驱动&#xff09;神经网络 RNN 分词&#xff08;数据驱动&#xff09…...

Easy Excel

Easy Excel 一、依赖引入二、基本使用1. 定义实体类&#xff08;导入/导出共用&#xff09;2. 写 Excel3. 读 Excel 三、常用注解说明&#xff08;完整列表&#xff09;四、进阶&#xff1a;自定义转换器&#xff08;Converter&#xff09; 其它自定义转换器没生效 Easy Excel在…...

OpenHarmony标准系统-HDF框架之I2C驱动开发

文章目录 引言I2C基础知识概念和特性协议&#xff0c;四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线&#xff0c;由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…...

使用python进行图像处理—图像变换(6)

图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切&#xff08;shear&#xff09;以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...