多线程基础篇

news2024/11/23 9:40:22

我们平常说的一个程序,一个程序中有声音,图片,字幕
实际上是一个进程中有多个线程

main线程是主线程。
多核,多个cpu,多个线程,切换的很快
单核的话是一个cpu,某一时间只能是一个线程,但是因为切换的很快, 因此有同时执行的错觉。

在一个进程中,如果开辟了多个线程,线程的运行是由调度器安排调度,调度器与操作系统紧密相关,先后顺序是不能认为干预的。
对同一份资源操作,会存在资源抢夺的问题,需要加入并发控制。
线程会带来额外的开销,cpu调度,线程的切换等

每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。ThreadLocal

创建线程的三种方式

1、继承thread类
2、实现Runnable接口
3、实现Callable接口

继承Thread类,重写run方法,调用start方法执行

在这里插入图片描述

实现Runnable接口,重写run方法,调用start方法执行

需要创建runnable接口的实现类对象,然后创建线程对象,通过线程对象开启线程,代理
在这里插入图片描述java是单继承,我们一般使用runnable接口创建线程。

在这里插入图片描述
这里我们可以看到一个对象可以被多个线程使用,换句话说就是多个线程会使用同一个资源,那么这里就会涉及到并发问题->线程安全问题->数据紊乱

实现Callable接口

在这里插入图片描述这里的创建服务的是一个池子。有几个线程,nThread就是多少
submit是提交执行线程。
在这里插入图片描述

Thread的常用方法

Thread currentThread()   //获取当前线程
Thread.currentThread().getName() //获取当前线程的名称 
setPriority(int newPriority)  //更改线程的优先级
getPriority()  //获取线程优先级
static void sleep(long millis) //休眠
static void yield()//当前线程对象暂停执行,执行其他线程,一直到其他线程执行完继续执行当前线程
void join() //插队相当于vip
void interrupt() //中断线程
boolean isAlive() //判断线程的是否存活
Thread.State getState()//获取线程的状态
setDaemon(true)  // 设置线程为守护线程

yield礼让线程,从运行状态转换为就绪状态,重新竞争资源,礼让不一定成功
join 霸道线程,直接插队,其他执行线程变成阻塞状态

如何优雅的暂停线程

stop/destroy是不推荐的
1、一般是通过一个标志位进行终止变量,flag=false
2、推荐线程自己停止,利用次数,不建议死循环

代理模式

静态代理:

前提:代理对象和目标对象要实现同一个接口。
就是代理对象中有目标对象,在代理对象的类中有一个方法调用了目标对象的方法。在实际使用的时候,实例化到了目标对象到代理对象中,然后代理对象调用方法。
好处:代理对象帮助目标对象做做不到的事情,目标对象只需要做自己的事情

动态代理

线程的状态

在这里插入图片描述
创建状态—new Thread()
就绪状态–start()
等待cpu调度,调度了就会运行–运行状态–线程执行线程体的代码块
阻塞状态—运行中的线程sleep了,也就是说cpu被抢夺
只有当阻塞状态接触,会重新进入就绪状态,等待cpu的调度。

Thread.State

在这里插入图片描述
NEW :新生状态
RUNNABLE :运行状态
BLOCKED :阻塞状态
WAITING:等待
TIME_WAITING:
TERMINATED:死亡
死亡后的线程不能再次启动。会报错的

线程的优先级

线程调度器是根据优先级来调度线程的,优先级高的最先被调度,同级的随机调度。
线程优先级用数字表示,范围是1-10

在这里插入图片描述

守护线程daemon

线程氛围用户线程和守护线程
虚拟机必须确保用户线程(main)执行完毕,虚拟机不用等待守护线程(gc)执行完毕。
比如后台记录日志,监控内存,垃圾回收等等都是守护线程。
当主线程运行完毕,虚拟机就关闭了,即使守护线程还在运行。

线程同步

线程同步其实就是一种等待机制,多个线程竞争这个资源的时候,会有一个对象的等待池形成队列,等待前面的线程使用完毕,下一个线程再使用。

队列和锁synochronized

线程同步需要队列和锁,每个对象都有一把锁,这样才能保证线程的安全性。

由于同一个进程的多个线程共享同一块存储空间,有数据的一个共享,因此会带来线程不安全和并发的问题,为了保证数据在方法中被访问时的正确性,我们在访问的时候加入锁机制synchronized,当一个线程获得对象的排它锁,就会独占资源,其他线程必须等待,当该线程使用完毕后会释放锁。
但可能会出现以下问题:在这里插入图片描述同步方法
public synchronized void method(int args){}
这个方法控制对对象的访问,每个对象都有一把锁,synchronized关键字是当访问这个方法的时候必须要获取对象的锁之后才可以访问。
弊端:锁住了整个方法,耗费资源
同步块
当方法里面有需要修改的内容才需要锁,因此出现了同步代码块

但是需要注意的是:synchronized是获取的当前对象的锁,默认锁的是this本身。因此我们需要使用同步块,同步块是同步监视器,可以监视任意对象,换句话说,锁的是共享资源。
在这里插入图片描述比如银行取钱,锁的应该是账户,多个线程访问账户的时候,都应该按照队列进行。因此我们需要使用的是同步代码快。
换句话说,锁的对象是变化的,需要增删改的对象。
synchronized是一个隐式锁,我们不知道他何时

JUC–线程安全集合CopyOnWriteArrayList

这个集合是java.util.concurrent包下的,java并发包下的
Arraylist是线程不安全的。
CopyOnWriteArrayList是线程安全的,不需要我们手动加锁。

死锁

Lock锁

从jdk5.0开始,jdk就提供了一个更强大的线程同步机制:通过显示定义同步锁对象来实现同步—Lock锁。
他是java.util.concurrent包下的,它拥有与synchronized相同的并发性和内存语义,可以显示加锁,释放锁。常用的有ReetrantLock锁(可重用锁)。
手动加锁,解锁
在这里插入图片描述简单应用:
加一个属性是ReetrantLock lock,
在run方法中手动加锁 lock.lock
手动释放锁:lock.unlock();

sycnchronized和lock的对比

1、lock是显式锁,需要手动加锁释放锁,synchronized是隐式锁,出了作用域就自动释放。
2、lock只有代码块锁,而synchronized有方法锁和代码块锁。
3、使用lock锁比使用synchronized锁的性能更好,有更好的扩展性
优先使用顺序
Lock>同步代码快>同步方法
在这里插入图片描述

线程通信

这个是线程同步的问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
对于生产者,没有生产产品之前,要通知消费者等待,生产产品之后要通知消费者消费。
对于消费者,在消费之后,要通知生产者已经结束消费,仍然需要产品消费。

在这里,synchronized是不同解决这个问题的,因为synchronized是锁住了共享资源,也就是变化的对象,只能保证对象的安全性,实现了同步,但是无法实现不同线程的消息传递。

解决方案:

通知 notify()
等待 wait()
在这里插入图片描述
在这里插入图片描述生产者–线程
消费者–线程
产品–普通类
缓冲池–普通类–有容器(集合或者数组)

使用线程池

在并发情况下,经常创建销毁线程对性能的影响很大。
因此我们选择使用线程池,提前创建好线程,放入线程池中,使用的时候直接获取,使用完后放回池中,实现重复利用。

优点:
1、提高响应速度
2、降低资源消耗
3、方便管理
线程池的大小corePoolSize
最大线程数maxinumPoolSize
线程没有任务时多久会终止keepAliveTime
线程池相关API:ExcutorService和Executors
ExecutorService:线程池接口。

常见子类:ThreadPoolExcutor
void  execute(Runnable command):执行任务,没有返回值,执行线程
<T>Future<T> submit(Callable<T> task):执行任务,有返回值,一般用来执行Callable
void shutdown()关闭连接池

Executors:线程池工具类,用于常见返回不同类型的线程池
Executors.newFixedThreadPool(int nThread)创建线程池,返回的是ExcutorService,参数nThread为线程池大小

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

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

相关文章

NLNet、GCNet、RTNet三种多头注意力网络的对比与分析

目录 一、中心思想 二、网络结构的异同点 三、网络结构的改进 3.1 GCNet的改进 3.2 RTNet的改进 四、总结 一、中心思想 三种网络最终目的都是为了捕获远程依赖关系或是全局上下文信息以增强目标检测或是目标分割的效果。 NLNet&#xff1a;卷积运算只能一次处理一个局…

C#,《小白学程序》第七课:列表(List)应用之一“编制高铁车次信息表”

1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary>…

17.CSS发光按钮悬停特效

效果 源码 <!DOCTYPE html> <html> <head><title>CSS Modern Button</title><link rel="stylesheet" type="text/css" href="style.css"> </head> <body><a href="#" style=&quo…

【Go 基础篇】探索Go语言中Map的神奇操作

嗨&#xff0c;Go语言的学习者们&#xff01;在编程世界中&#xff0c;Map是一个强大而又有趣的工具&#xff0c;它可以帮助我们高效地存储和操作键值对数据。Map就像是一本字典&#xff0c;可以让我们根据关键字&#xff08;键&#xff09;快速找到对应的信息&#xff08;值&a…

Windows版本Docker安装详细步骤

文章目录 下载地址安装异常处理docker desktop requires a newer wsl 下载地址 https://desktop.docker.com/win/stable/Docker%20Desktop%20Installer.exe 安装 双击下载的文件Docker Desktop Installer.exe进行安装 点击OK 开始安装 安装完成点击Close and restart&…

JavaScript—面向对象、作用域

C#&#xff1a;从类继承 js&#xff1a;从对象继承 什么叫继承&#xff1f; 模板&#xff08;类&#xff09; 原型继承&#xff08;实体&#xff09; 有一个对象存在&#xff0c;构造函数设置原型为这个对象 创建出来的对象就继承与这个对象&#xff08;从对象那里继承&am…

ElasticSearch基础知识汇总

文章目录 前言一、认识ElasticSearch1.正向索引和倒排索引2. MySql与ElasticSearc3.IK分词器 二、ES索引库操作1.mapping映射属性2.索引库的CRUD 三、ES文档库操作 前言 Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基…

Kali Linux进行移动应用安全测试

使用Kali Linux进行移动应用安全测试是一项关键任务&#xff0c;可以帮助识别和修复移动应用中的安全漏洞。以下是一个基本的步骤指南&#xff0c;展示如何在Kali Linux中进行移动应用安全测试。 步骤&#xff1a; 准备环境&#xff1a; 确保 已经安装了Kali Linux&#xff0c…

开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Function)

文章目录 前言 C MEX S-Function 算法原理 原始信号创建 编写S函数 仿真验证 Tips 分析和应用 总结 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;一&#xff09;——powergui模块》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用…

fastjson利用templatesImpl链

fastjson1.2.24 环境&#xff1a; pom.xml&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLoc…

在 Python 中逐步构建 DCF(贴现流)估值

Building A DCF Valuation in Python, Step by Step | by Roi Polanitzer | Medium 说明 这是一个真实的&#xff0c;以色列国土内的公司业务评估案例。在本文中&#xff0c;我将演示如何使用python中的DCF方法对以色列系统和应用程序公司进行业务评估。因为存在许多业务术语&a…

JVM 访问对象的两种方式

Java 程序会通过栈上的 reference 数据来操作堆上的具体对象。由于 reference 类型在《Java 虚拟机规范》里面只规定了它是一个指向对象的引用&#xff0c;并没有定义这个引用应该通过什么方式去定位、访问到堆中对象的具体位置&#xff0c;所以对象访问方式也是由虚拟机实现而…

音视频技术开发周刊 | 308

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 OpenAI首席科学家最新访谈&#xff1a;对模型创业两点建议、安全与对齐、Transformer够好吗&#xff1f; OpenAI首席科学家Ilya Sutskever最近和他的朋友Sven Strohband进…

算法设计 || 第6题:基于最小成本检索的分支界限算法求解15谜问题

用基于最小成本检索的分支界限算法求解15谜问题 要求利用成本估计函数C^(X)&#xff0c; C^(X)为节点x排列中不在其目标位置上的牌的总张数&#xff08;不包括空格牌&#xff09;。 现定义空格牌的上下左右四种活动&#xff0c; 按四种活动分别生成其状态空间树&#xff0c;…

JVM,JRE和JDK的区别

JVM&#xff0c;JRE和JDK的区别 JVM(Java Virtual Machine&#xff0c;Java虚拟机)JREJRE目录结构 JDK JVM(Java Virtual Machine&#xff0c;Java虚拟机) Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行&#xff0c;Java虚拟机中…

Docsify的评论系统gitalk配置过程

&#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;开源建设者与全栈领域优质创作者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 我的博客&#xff1a;Zeeland&#x1f4da; Github主页: Undertone0809 (Zeeland)&…

[元带你学: eMMC协议 31] eMMC Context(上下文) ID 详解 | eMMC 并行数据标识与隔离详解

依JEDEC eMMC及经验辛苦整理,原创保护,禁止转载。 专栏 《元带你学:eMMC协议》 内容摘要 全文 5000 字, 主要内容 eMMC 为什么要引入 Context? Context 是什么? 如何使用Context 上下文? Context 上下文配置怎么做? 上下文 ID 应用局限 系统层和芯片组对 Contex…

IEC 60068 环境测试介绍及其标准下载

IEC 60068 环境测试介绍及其标准下载 IEC 60068 标准由国际电工委员会 (IEC) 发布&#xff0c;是用于电工产品环境测试的国际标准。 IEC 60068 系列包含有关标准、环境测试程序和测试严重性的基本信息。 IEC 60068 环境测试 制定这一系列标准是为了在特定产品类型&#xff08…

这是一条求助贴(postman测试的时候一直是404)

看到这个问题是404的时候总感觉不该求助大家&#xff0c;404多常见一看就是简单的路径问题&#xff0c;我的好像不是&#xff0c;我把我的问题奉上。 首先我先给出我的url http://10.3.22.195:8080/escloud/rest/escloud_contentws/permissionStatistics/jc-haojl/sz 这是我…

Midjourney学习(一)prompt的基础

prompt目录 sd和mj的比较prompt组成风格表现风格时代描述表情色彩情绪环境 sd和mj的比较 自从去年9月份开始&#xff0c;sd就变得非常或火&#xff0c;跟它一起的还有一个midjourney。 他们就像是程序界的两种模式&#xff0c;sd是开源的&#xff0c;有更多的可能性更可控。但是…