多线程基础篇

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

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为线程池大小

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

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

相关文章

抢先体验|乐鑫推出 ESP32-S3-BOX-3 新一代开源 AIoT 开发套件

乐鑫科技 (688018.SH) 非常高兴地宣布其开发套件阵容的最新成员 ESP32-S3-BOX-3。这款完全开源的 AIoT 应用开发套件搭载乐鑫高性能 ESP32-S3 AI SoC&#xff0c;旨在突破传统开发板&#xff0c;成为新一代开发工具的引领者。 【乐鑫新品抢先体验】ESP32-S3-BOX-3 新一代开源 A…

WPF基础入门-Class3-WPF数据模板

WPF基础入门 Class3&#xff1a;WPF数据模板 1、先在cs文件中定义一些数据 public partial class Class_4 : Window{public Class_4(){InitializeComponent();List<Color> test new List<Color>();test.Add(new Color() { Code "Yellow", Name &qu…

数据库中的条件索引使用

数据库条件索引 在逻辑删除相关的表中&#xff0c;设置普通唯一索引在多个逻辑上已删除的元组中可能发生唯一性冲突&#xff0c;即不允许存在两个相同的已删除元组&#xff0c;同时在存在已删除元组时也不允许插入相同值的新元组。此时可以通过设置条件索引&#xff0c;使唯一…

PlantUML文本绘制类图

记录下文本绘制类图的语法 参考 https://juejin.cn/post/6844903731293585421 类的UML表示 使用UML表示一个类&#xff0c;主要由三部分组成。类名、属性、方法。其中属性和方法的访问修饰符用 - 、# 、 表示 private、protected、public。 如图所示&#xff0c;表示A类有一个…

【java】获取当前年份

目录 一、代码示例二、截图示例 一、代码示例 package com.learning;import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.Year; import java.util.Calendar; import java.util.Date;/*** 获取当前年份*/ public class GetCurrentYear {public …

苹果备货量创新高,潜望镜头立大功,iPhone 15 Pro Max备受瞩目

根据郭明锤的简讯内容&#xff0c;关于苹果公司未来发布的iPhone 15系列&#xff0c;有一些令人振奋的消息。据预测&#xff0c;苹果公司计划于下个月发布iPhone 15系列&#xff0c;其中最高配置的机型iPhone 15 Pro Max备货量预计将占整个系列的35%至40%&#xff0c;这一比例超…

46、基于51单片机的电子闹钟(DS1302)(程序+Protues仿真)

编号&#xff1a;46 基于51单片机的电子闹钟&#xff08;DS1302&#xff09; 功能描述&#xff1a; 本设计由51单片机最小系统DS1302时钟模块液晶1602显示模块键盘模块 1、主控制器是89C82单片机 2、DS1302获取时钟数据&#xff1b; 3、液晶1602显示年、月、日、时、分、秒、…

老Python程序员职业生涯感悟—写给正在迷茫的你

我来讲几个极其重要&#xff0c;但是大多数Python小白都在一直犯的思维错误吧&#xff01;如果你能早点了解清楚这些&#xff0c;会改变你的一生的。所以这一期专门总结了大家问的最多的&#xff0c;关于学习Python相关的问题来给大家聊。希望能带给大家不一样的参考。或者能提…

Linux 查看当前文件夹下的文件大小

1.直接查看: ll 或者 ls -la #查看文件大小&#xff0c;以kb为单位 ll#查看文件大小&#xff0c;包含隐藏的文件&#xff0c;以kb为单位 ls -la2.以 M 或者 G 为单位查看&#xff0c;根据文件实际大小进行合适的单位展示 du -sh *

vxe-table中树形结构

如图&#xff0c;同事让帮忙实现一个需求 从二级树节点开始&#xff0c;同时选中的只能有一个二级树节点&#xff0c;选中的二级树节点之下的子节点都可以被选中。否则不能被选中 直接上代码 需要注意的是&#xff0c;文中树状图传递的数据是打平的数据&#xff0c;设置代码是…

【Terraform学习】使用 Terraform创建Lambda函数启动EC2(Terraform-AWS最佳实战学习)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

20 - 分页

分页相关方法 # paginate(当前页, 每页显示几条):分页;返回一个对象 pagination 模型类.query.order_by(-模型类.对象).paginate(page2, per_page3) print(pagination.items) # [<Article 2>, <Article 3>] :每页的数据对象 print(pagination.page) # 当前的页…

【高阶数据结构】map和set的介绍和使用 {关联式容器;键值对;map和set;multimap和multiset;OJ练习}

map和set的介绍和使用 一、关联式容器 关联式容器和序列式容器是C STL中的两种不同类型的容器。 关联式容器是基于键值对的容器&#xff0c;其中每个元素都有一个唯一的键值&#xff0c;可以通过键值来访问元素。关联式容器包括set、multiset、map和multimap。 序列式容器是…

聚焦磷酸铁锂产线革新,宏工科技一站式解决方案

兼顾了低成本与安全性两大属性&#xff0c;磷酸铁锂市场在全球范围内持续升温&#xff0c;并有望保持较高的景气度。巨大的需求空间之下&#xff0c;行业对于锂电装备企业的自动化与智能化水平、整线交付能力、产品效率与稳定性等均提出了新的要求。 以宏工科技股份有限公司&a…

MySql014——分组的GROUP BY子句排序ORDER BYSELECT子句顺序

前提&#xff1a;使用《MySql006——检索数据&#xff1a;基础select语句&#xff08;使用products表、查询单列、多列、所有列、DISTINCT去除重复行、LIMIT限制返回结果的行数、了解完全限定&#xff09;》中创建的products表 一、GROUP BY子句基础用法 SELECT vend_id, COU…

【ArcGIS Pro二次开发】(63):批量更改字段别名

在我工作中遇到的大多数图斑&#xff0c;字段名称一般是英文&#xff0c;字段别名是中文&#xff0c;使用起来是比较方便的。 但有时候也会遇到一些不一样的情况&#xff0c;不知是经过了怎样的处理&#xff0c;图斑的字段别名被修改成了和字段名称一样的英文&#xff0c;这样…

仓储23代拣货标签操作指导

服务器使用 V1.4基站已经内置服务程序&#xff0c;无需搭建服务&#xff1b;可跳至第1.4部分 服务器搭建 安装mysql5.7, 创建db_wms数据库并导入原始数据库文件 安装jdk1.8, 配置java环境变量 下载tomca8.0, 部署wms.war到tomcat, 并启动tomcat 下载资源 Windows 64bit: …

HTTP原理与实现

一、基本概念 一、基本原理* 1、全称&#xff1a; HyperText Transfer Protocol (超文本传输协议) 2、底层实现协议&#xff1a;建立在 TCP/IP 上的无状态连接。 3、基本作用&#xff1a;用于客户端与服务器之间的通信&#xff0c;规定客户端和服务器之间的通信格式。包括请…

Remmina在ubuntu22.04中无法连接Windows

Remmina在ubuntu22.04中无法连接Windows 问题 提示为&#xff1a; 无法通过TLS到RDP服务器… 分析 原因是Remmina需要使用openssl通过RDP加密与Windows计算机连接&#xff0c;而ubuntu22.04系统中OpenSSL版本为3.0&#xff0c;Openssl3 将 tls<1.2 和 sha1 的默认安全级别…

scikit-learn中OneHotEncoder用法

One-Hot编码&#xff0c;又称为一位有效编码&#xff0c;是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值&#xff0c;然后&#xff0c;每个整数值被表示为二进制向量&#xff0c;将整数索引标记为1&#xff0c;其余都标为0。 OneHotEncoder()常用参数解释 …