《java并发编程之美》第一章(主打一个陪伴学习)

看书总结记录,《java并发编程之美》,第一章。

1.1、什么是线程?

进程是代码在数据集合上的一次运行活动,是系统进行资源分配的基本单位。线程则是进程的一个执行路径,一个进程至少有一个线程,线程共享进程的堆、方法区等资源;但是每个线程又有自己独占的栈和程序计数器。

1.2、线程的创建

线程的创建有三种方法:

1、方法一:继承Thread类,重写run()方法。缺点是,java的单继承和任务(run())与代码没有分离,同一个任务逻辑要执行多个的时候,每一个都要创建一份任务代码。

2、方法二:实现Runnable接口(任务类),并重写run()方法,然后new Thread(Runnable)。java的接口可以实现多个,缺点是(方法一也存在),任务执行完成后无返回值。

3、方法三:通过FutrueTask来创建线程。先是创建任务类,具体为实现Callable接口,并重写call()方法,然后new Thread(Callable),任务结束之后有返回值。

1.3、线程的一系列方法

1、wait():想要一个线程去调用一个共享变量的wait()方式时,必须先获取到这个共享变量的监视器锁,不然会抛IllegaMonitorStateException。获取监视器锁的方法有两种:

a、执行synchronized静态代码块时,使用该共享变量做参数。

b、调用该共享变量的方法,并且该方法使用了synchronized修饰。

调用这个wait()方法后,线程会阻塞挂起,直到发生以下事件才会返回:

a、其它线程调用了该共享变量的notify()方法或者notifyAll()方法。(notify:通知)

b、其它线程调用了该线程的interrupt()方法中断,抛出中断异常(InterruptException)。

wait(long timeout):指定等待时间。

wait(long timeout,int nanos):当nacos>0时,timeout++。

2、notify():一个线程调用共享对象的notify()方法之后,会唤醒一个在该共享变量上调用的一个线程。和wait系列方法一样,它也需要这个线程先获取到该共享变量的监视器锁。

notifyAll():唤醒全部在该共享变量上调用的线程。

3、join():等待线程终止的方法,使用场景:比如多线程去获取资源,要全部加载完毕后,再汇总处理。

4、sleep():睡眠期间让出指定时间的执行权,不参与CPU调度,但是不会让出其所拥有的监视器资源,比如锁。睡眠期间,如果其它线程调用该线程的interrupt()方法,会抛出中断异常InterruptedException。

5、yield():线程调用这个方法,让出cpu执行权,当前线程回到就绪状态。

6、interrupt():其它线程调用当前线程的interrupt方法的话,会给当前线程设置一个中断标志,但是也仅仅是设置中断的标志,当前线程还是会继续执行下去。但是如果当前线程是出于一个wait()阻塞挂起,或者sleep()阻塞睡眠,或者join()阻塞的时候,当前线程会抛出中断异常InterruptException。

boolean IsInterrupted():检测当前线程是否被中断。

boolean interrupted():检测当前线程是否被中断,如果是中断的话,并会清理中断标志,并且它获取的是当前线程的中断标志,而不是调用这个方法的线程的中断标志。

1.4、线程死锁

死锁的产生必须具备的四个条件:

1、互斥条件:指线程对已经获取到的资源进行排它性使用,即该资源同时只由一个线程占用。如果此时有别的线程请求获取该资源,则请求者只能等待,直至占有资源的线程释放该资源。

2、请求并持有条件:指一个线程已经持有了至少一个资源,但又提出了新的资源请求,而且新资源已经其它线程占有,所以当前线程会阻塞,但是阻塞的同时并不释放自己已经获取了的资源。

3、不可剥夺条件:指线程获取到的资源在自己使用完之前不能被其它线程抢占,只能在自己使用完毕后,由自己释放。

4、环路等待条件:指发生死锁的时候,必定存在一个线程——资源的环形链。

避免死锁的方法:目前只有请求并持有和环路等待条件是可以被破坏的。比如可以让线程的资源请求顺序保持一致。

1.5、守护线程与用户线程

thread.setDaemon(true),可以将线程设置为守护线程。守护线程和用户线程的区别在于,当最后一个非守护线程结束后,JVM会正常退出,而不管当前的守护线程是否还没结束。

1.6、ThreadLocal

线程本地变量,如果创建了一个ThreadLocal变量后,那么在访问这个变量的时候,每个线程会复制一个变量到自己的本地内存。 所谓ThreadLocal变量就是保存在每一个线程的ThreadLocalMap中的。而这个map是也特殊的map,因为它的entry的key是一个弱引用。如果这个变量不再被其他对象使用时,可以自动回收这个ThreadLocal对象,避免可能的内存泄露。但是它的value是强引用,只有在线程thread回收时,它在会被回收。为了解决这个问题,就需要在这个变量使用完之后,调用remove()方法删除这个本地变量。

InheritableThreadLocal:继承自ThreadLocal,其提供一个特性,就是让子线程可以访问在父线程中设置的本地变量。比如子线程想要获取到父线程设置的用户登录信息等。

Java并发编程之美 文章被收录于专栏

本专栏是本人看书——《java并发编程之美》的总结,主要是为自己做一个记录,也欢迎大家评论区留言讨论交流呀~

全部评论

相关推荐

04-12 21:52
南开大学 Java
鼠鼠有点摆,去年边学着没敢投简历,没实习。从1月到现在总共面了五次,四次字节的日常(HR打电话约面试才敢去的),然后一次腾讯的暑期,都是一面挂,其他则是没给面。暑期的岗,4.2才开始海投,前面想着等字节第四次一面后再投,结果挂,而且感觉投晚了。字节投了11个,9个简历挂,剩下2个没动静。阿里全都简历挂,剩下的在"投递简历"。腾讯给了一次面。然后其他大中厂、手机厂什么的都是做完测评or笔试就没下文,打开几个看也是终止流程,感觉剩下的也应该是简历挂了。感觉是简历的原因?项目部分,几次面试,感觉面试官主要就拷问过秒杀这一个点。自己说的时候会尝试把sse那条说成亮点,但除了腾讯面试官问过一下这整个点在业务方面对用户有什么用之类的问题外,其他最多只是问一下sse八股...感觉也许不是很让面试官感兴趣。这个短链接也是无人问津,就被问过一回雪花算法的设计。也许我该拿点评改改,然后再在网上找一个什么项目,凑两个,而不是用自己现在这两个项目?或者是点评改改放前面,然后原本第一个项目,把秒杀抽掉,剩下的想办法从网上火的RAG项目里移植点亮点,或者直接就用网上的RAG项目?感觉我主要还是偏向后端开发,但是感觉如果除开点评,再拿一个项目,想不到有什么自己能掌控且跟点评不重的。然后鼠鼠之前主要的问题是担心面试让打开项目演示,然后就一直花时间在用AI整第一个项目,第二个项目都没时间整,第四次面试之前还因为太害怕被认为不熟悉项目,跟AI一起把简历的说辞做了大幅度弱化,然后暑期都是拿弱化后的简历投的,感觉是不是看上去太没有吸引力就直接给简历挂了。(图1是弱化后的,图2是弱化前的,但之前3月初投了几家好像也是简历挂。)而且因为3月花了很多时间整在跟AI整代码,导致八股和算法都没怎么看,算法之前有跟灵神题单刷一些,还算入门,但是八股只看了一些基本的,可能面试的时候只答得上来60-70%,而且表述有些混乱,都是想到哪说到哪;前面几回面试基本上都有大板块的基础八股没答出来,比如RedisZ Set数据结构,MQ延时消息、可靠性保证,JVM内存分配的过程、GC roots,JUC锁,设计模式。现在有点不知道该怎么办。求大佬们给点简历修改建议或者面试准备建议,不胜感激!
何时能不做牛马:简历每个点之间的间距可以缩一下。几乎没遇到过要演示项目的情况,即使万一遇上了你也可以说部署在其他电脑上本地没代码。nku不应该简历挂吧?抓紧背背八股练练表达,不要放弃,五六月份找到也不晚(不然还得提前入职
应届生简历当中,HR最关...
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务