线程

简介: 多线程

java虚拟机用的是那种内存模型呢?
1.ULT(用户线程)
2.KLT(内核线程)

实现Callable接口
1.实现Callable接口,需要返回值类型
2.重写call方法,需要抛出异常
3.创建目标对象
4.创建执行服务:ExecutorService ser = Executos.newFixedThreadPool(1);
5.提交任务Future result = ser.submit(t1);
6.获取结果boolean r1 = result.get();
7.关闭服务。ser.shutdownNow();

线程休眠:
1.sleep(时间)指定当前线程阻塞的毫秒数
2.sleep存在异常InterruptedException
3.Sleep时间达到后线程进入就绪状态
4.Sleep可以模拟网络延时,倒计时等。
5.每一个对象都有一个锁,sleep不会释放锁。

线程礼让:yield()
1.礼让线程,让当前正在执行的线程暂停,但不阻塞。
2.将线程从运行状态转为就绪状态
3.让cpu重新调度,礼让不一定成功,看cpu心情。

线程的状态。新生,就绪,运行,阻塞,死亡
1.new(新生):尚未启动的线程处于此状态,Thread t= new Thread();
2.Runnable(运行):在java虚拟机中执行的线程处于此状态
3.Blocked(阻塞):被阻塞等待监视器锁定的线程处于此状态
4.Waiting(阻塞):正在等待另一个线程执行特定动作的线程处于此状态。
5.Time_Waiting(阻塞):正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
6.terminated(死亡):已退出的线程处于此状态。

新生:尚未启动的线程处于此状态,Thread t= new Thread();
就绪:当调用start()方法后,线程立即进入就绪状态,但不意味着立刻调度执行。
运行:进入运行状态,线程才真正执行线程体的代码块。
阻塞:当调用sleep,wait或者同步锁定时,线程进入阻塞状态,就是代码不往下执行,阻塞时间解除后,重新进入就绪状态,等待cpu调度。
死亡:线程中断或者结束,一旦进入死亡状态,就不能再次启动。

一个线程可以在指定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。

线程的优先级:
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
线程的优先级用数字表示,范围从1—10。
Thread.MIN_PRIORITY =1;
Thread.MIN_PRIORITY =10;
Thread.NORM_PRIORITY =5;
使用以下方式改变或获取优先级
getPriority().setPriority(int XXX)
优先级的设定建议再start()调度前
优先级低只是意味着获得调度的概率低,并不是优先级就不会被调用了,这都是看cpu的调度。

守护(daemon)线程:
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕 (main() 就是用户线程)
虚拟机不用等待守护线程执行完毕,如,后台记录操作日志,监控日志,垃圾回收等待。(守护线程)

线程同步
多个线程操作同一个资源。
并发:同一个对象被多个线程同时操作。
形成条件:队列+锁。
处理多线程时,多个线程访问同一个对象,并且某些线程还想修改这个对象,这是我们就需要线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。
由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突问题,为了保证数据在方法中被访问的正确性,在访问时加入锁机制Synchronized,当一个线程获得对象的排他锁,独占资源,其他线程必须等待,使用后释放锁即可,存在以下问题:

1.一个线程持有锁会导致其他所有需要此锁的线程挂起。
2.在多线程竞争下,加锁,释放锁会导致比较多的上下文切换和调度延时,引起性能问题;
3.如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能问题。

同步方法:
由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是Synchronized关键字,它包括两种用法:Synchronize方法和Synchronize块。
同步方法:public Synchronize void method(int args){}

Synchronize方法控制对“对象”的访问,每个对象对应一把锁,每个Synchronize方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行。
缺陷:若将一个大的方法申明为Synchronize将会影响效率。
方法里面需要修改的内容才需要加锁,锁的太多,浪费资源。

死锁:
多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个欧折多个线程都在等待对方释放资源,都停止执行的情形,某一个同步块同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题。

产生死锁的四个必要条件:
1.互斥条件:一个资源每次只能被一个进程使用。
2,请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

线程通信的应用场景:生产者消费者模式。
假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走消费。
如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,知道仓库中的产品被消费者取走为止。
如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止。
分析:
这是一个线程同步的问题,生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。
在生产者消费者问题中,仅有Synchronized是不够的

Synchronized可阻止并发更新同一个共享资源,实现了同步。
Synchronized不能用来实现不同线程之间的消息传递(通信)。

java提供了几个方法解决线程之间的通信问题:
wait() :表示线程一直等待,直到其他线程通知,与slepp不同,wait会释放锁。
wait(long tiomeout) :指定等待的毫秒数。
Notify():唤醒一个处于等待的线程。
notifyAll():唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度。
注意:均为Object类方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常。

解决方式1:并发协作模型“生产者/消费者模式”——>管程法
1.生产者:负责生产数据的模块(可能是方法,对象,线程,进程)
2.消费者:负责处理数据的模块(可能是方法,对象,线程,进程)
3.缓冲区:消费者不能直接使用生产者的数据,他们之间有个“缓冲区”
生产者将生产好的数据放入缓冲区,消费者从缓冲区拿出数据。
解决方式2:并发协作模型“生产者/消费者模式”——>信号灯法—设置标志位。

线程池:
背景:经常创建和销毁,使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中,可以避免频繁创建销毁,实现重复利用。类似生活中的公共交通工具。
好处:
1.提高响应速度(减少了创建新线程的时间)
2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
3.便于线程管理。

corePoolSize:核心线程数
maximumPoolSize:最大线程数

线程池面试题:
1.单核cpu设定多线程是否有意义?
答:有意义,因为你的线程并不是所有的时间都在占用cpu,有的线程在等待网络的输入,所以让其余线程轮流执行;
2.工作线程数是不是越大越好?
答:不是,线程之间有切换,切换本身开销就挺大。
3.工作线程数(线程池中线程核数量)设置多少合适?
答:公示:

Nthreads = Ncup * Ucpu *(1+W/C)

其中:
Ncup是处理器的核的数目,可以通过Runtime.getRuntime().availableProcessors()得到;
Ucpu是期望的cpu利用率(该值一般在0-1之间);
W/C是等待时间与计算时间的比率。(W:wait的时间/C:计算的时间)

例如:8核的cpu,期望每个cpu的利用率为50%,等待时间是0.5,计算时间0.5;则计算工作线程数
=80.5(1+0.5/0.5)=8;
线程的等待时间怎么来的:压测,做统计,调整,在生产环境要根据日志观察

并发编程的三大特性:
可见行:(visibility)
有序性: ( ordering)
原子性: (atomicity)

1.内存中的一行数据有多大:64个字节,为什么是64byte:
答:当块越大的时候,速度很慢,当块很小的时候,缓存中的命中率又很低。所以经过一系列的实测取了折中值64。

2.有序性:程序真的是按照“顺序”执行的吗?
x=1 x=1
x++ y=1
为了提高执行效率,cpu指令可能会乱序执行。
乱序执行不得影响单线程的最终一致性。

乐观锁:(认为别人没有修改)
CAS: 原来有个值0,好多线程要对0进行递增,每个线程将0读出来,要改变成1,然后把1往回写,看原本的数字是不是还是0,如果是0,则修改为1;
如果发现原来的0已经改变,比如已经被别的线程改成8,则重新读出来,再递增;继续判断。

1.怎么解决cas中ABA过程
Jdk提供了两个类。

自定义线程池:

1.execute()和submit的区别:

 答:submit()有返回值,是Future类型的;execute()没有返回值;submit是异步,execute是同步。

submit()可以传Runnable,Callable; execte()只能传Runnable。
核心线程默认不会死,可以去设置。
第3,4个参数说的是非核心线程数的最长空闲时间。
执行顺序:
corePoolSizw:当进来线程任务的时候,线程池新创建线程来执行任务,当线程池中的线程数且达到核心线程数后,就会把到达的任务放在缓存队列中;
maxPoolSize:当线程数>=核心线程,且队列已满时,线程池会创建新的线程,直至达到最大线程数。
注意:当达到核心线程数,并且队列已经满了的时候,再进来线程任务时,此时会创建新的非核心线程,来执行新进来的任务,并不是先执行队列里的。

相关文章
|
缓存 资源调度 JavaScript
nodejs全局(npm、cnpm、yarn)及缓存基本配置,一篇就搞定
nodejs全局(npm、cnpm、yarn)及缓存基本配置,一篇就搞定
|
运维 监控
"网络工程师必备秘籍:4大招轻松破解M-LAG故障难题,你的网络还能更稳定!"
【8月更文挑战第19天】M-LAG技术通过多链路聚合提升网络可靠性和带宽。面对M-LAG故障,四步定位法助您迅速排障:1) 检查M-LAG成员状态确保链路活动;2) 验证链路聚合配置一致;3) 分析控制和平面与数据平面状态;4) 排除物理层故障如端口状态异常。结合网络监控和定期检查,保障M-LAG稳定运行。
494 0
|
Web App开发 JSON iOS开发
抖音 根据视频id获取视频详情接口分析
抖音 根据视频id获取视频详情接口分析
1840 0
抖音 根据视频id获取视频详情接口分析
|
Java Maven 应用服务中间件
Maven项目发布时lib目录没有jar包的解决办法
背景 IntelliJ IDEA 中用 Maven 构建SSM项目并发布到Tomcat。 问题 发布时报错找不到类,经查找发布出的lib文件夹里并没有任何的jar包。
3676 0
|
安全 虚拟化 芯片
MacOs13 Ventura(M1/M2芯片) + Parallels Desktop 18(PD18史上最强虚拟机)永久免费使用攻略
众神殿内,高朋满座,胜友如云,Vmware、VirtualBox、Utm等虚拟机大神群英荟萃,只见位于C位王座上的Parallels怅惘抬头,缓缓逡巡,睥睨群小,目光到处,无人敢抬头对视。 是的,如果说虚拟机领域有一位王者,非Parallels不能领袖群伦,毕竟大厂背书,功能满格,美中不足之处就是价格略高,但这也并非是Parallels的错,因为市场上没有任何一款虚拟机产品在产品力层面能和Parallels抗衡,本次我们在最新的MacOs13 Ventura(M1/M2芯片)系统下永久使用Parallels Desktop 18.1.0版本。
MacOs13 Ventura(M1/M2芯片) + Parallels Desktop 18(PD18史上最强虚拟机)永久免费使用攻略
|
NoSQL 应用服务中间件 nginx
Docker容器化技术实战操作汇总(附开发环境搭建)
docker是什么: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
911 0
Docker容器化技术实战操作汇总(附开发环境搭建)
|
前端开发 JavaScript 网络协议
Vue中 使用 WebSocket
Vue中 使用 WebSocket
584 0
Vue中 使用 WebSocket
|
存储 Java
java:int强制类型转换成byte
int 在java中是32位, byte是8位 原码:就是二进制码,最高位为符号位,0表示正数,1表示负数,剩余部分表示真值 反码:在原码的基础上,正数反码就是他本身,负数除符号位之外全部按位取反 补码:正数的补码就是自己本身, 负数的补码是在自身反码的基础上加1
java:int强制类型转换成byte
|
存储 人工智能 达摩院
ICASSP 2022 多通道多方会议转录挑战项目(M2MeT)成功举办
近日,ICASSP 2022 多通道多方会议转录挑战(M2MeT)完成了测试集评测及结果公布。本次挑战由阿里巴巴达摩院语音实验室和希尔贝壳联合举办,多位国际知名行业专家包括达摩院语音实验室负责人鄢志杰、研究员马斌,希尔贝壳CEO卜辉,希尔贝壳基金会谢磊教授,美国俄亥俄州立大学汪德亮教授,丹麦奥尔堡大学谭政华教授,上海交通大学钱彦旻教授,新加坡A*STAR资讯通信研究院高级科学家Kong Aik Lee等参与大会组织和评审。
902 0
ICASSP 2022 多通道多方会议转录挑战项目(M2MeT)成功举办
|
存储 程序员 Linux
重学计算机组成原理(十二) - 异常和中断(下)
重学计算机组成原理(十二) - 异常和中断(下)
451 0
重学计算机组成原理(十二) - 异常和中断(下)