java程序设计基础,Java线程基础进阶-程序员宅基地

技术标签: 程序员  java  开发语言  

  • 线程并发安全问题认知强化

    • 如何理解线程安全与不安全?
  • 导致线程不安全的因素有哪些?

  • 如何保证并发线程的安全性?

  • 如何理解JAVA中的悲观锁和乐观锁?

  • 如何理解线程的上下文切换?

  • 如何理解死锁以及避免死锁问题?

  • 线程通讯与进程通讯应用增强

    • 如何理解进程与线程通讯?
  • 如何实现进程内部线程之间的通讯?

    • 基于wait/nofity/notifyall实现
  • 基于Condition实现

  • 如何实现进程之间间通讯(IPC)?

  • 总结(Summary)

进程与线程认知强化

===================================================================

如何理解进程与线程?


  • 进程:操作系统进行资源调度和分配的基本单位(例如浏览器,APP,JVM)。

  • 线程:进程中的最小执行单位(可以理解为一个顺序的执行流)。

在这里插入图片描述

说明:同一个进程内的多个线程共享资源。

如何理解多线程中的并行与并发?


并发:多线程抢占CPU,可能不同时执行,侧重于多个任务交替执行。

在这里插入图片描述

现在的操作系统无论是windows,linux还是macOS等其实都是多用户多任务分时操作系统,使用这些操作系统的的用户可以“同时”干多件事情。但实际上,对于单机CPU的计算机而言,在同一时间只能干一件事,为了看起来像是“同时干多件事”分时操作系统把CPU的时间划分成了长短进本相同的时间区间,即“时间片”,通过操作系统的管理,把时间片依次轮流的分配给各个线程任务使用。我们看似的“同时干多件事”,其实是通过CPU时间片技术并发完成的。例如:多个线程并发使用一个CPU资源并发执行任务的线程时序图。

在这里插入图片描述

并行:线程可以不共享CPU,可每个线程一个CPU同时执行多个任务。

在这里插入图片描述

总之:个人认为并行只出现在多CPU或多核CPU中,而并发可理解为并行中的一个子集。

如何理解线程的生命周期及状态变化?


一个线程从创建,运行,到最后销毁的这个过程称之为线程的生命周期,在这个生命周期过程中线程可能会经历如下几个状态:

在这里插入图片描述

这些状态可归纳为:状态分别为新建状态,就绪状态,运行状态,阻塞状态,死亡状态。

线程并发安全问题认知强化

======================================================================

如何理解线程安全与不安全?


  • 多个线程并发执行时,仍旧能够保证数据的正确性,这种现象称之为线程安全。

  • 多个线程并发执行时,不能能够保证数据的正确性,这种现象称之为线程不安全。

案例分享:如何保证12306中的订票操作的安全。

第一步:编写售票任务类:

class TicketTask implements Runnable{

int ticket=10;

@Override

public void run() {

doTicket();

}

public void doTicket() {

while(true) {

if(ticket<=0)break;

System.out.println(ticket–);

}

}

}

第二步:编写售票测试方法:

public static void main(String[] args) {

TicketTask task=new TicketTask();

Thread t1=new Thread(task);

Thread t2=new Thread(task);

Thread t3=new Thread(task);

t1.start();

t2.start();

t3.start();

}

导致线程不安全的因素有哪些?


  1. 多个线程并发执行。

  2. 多个线程并发执行时存在共享数据集(临界资源)。

  3. 多个线程在共享数据集上的操作不是原子操作。

例如:现有一生产者消费者模型,生产者和消费者并发操作容器对象。

在这里插入图片描述

如何保证并发线程的安全性?


第一;对共享进行限制访问(例如加锁:syncronized,Lock)

第二:基于CAS实现非阻塞同步(基于CPU硬件技术支持)

第三:取消共享,每个线程一个对象实例(例如threadlocal)

说明:Java中的线程安全问题的主要关注点有3个:可见性,有序性,原子性;

Java内存模型(JMM)解决了可见性和有序性问题,而解决了原子性问题。

如何理解JAVA中的悲观锁和乐观锁?


JAVA中为了保证多线程并发访问的安全性,提供了基于锁的应用,大体可归纳为两大类,即悲观锁和乐观锁。

悲观锁&乐观锁定义说明:

1)悲观锁:假定会发生并发冲突,屏蔽一切可违反数据完整性的操作,例如java中可以基于syncronized,Lock,ReadWriteLock等实现。

  1. 乐观锁实现:假设不会发生冲突,只在提交操作时检查是否违反数据完整性,例如java中可借助CAS( Compare And Swap)算法实现(此算法依赖硬件CPU)。

悲观锁&乐观锁应用场景说明:

1)悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。

2)乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升

悲观锁&乐观锁应用案例分析

悲观锁实现计数器:

方案1:

class Counter{

private int count;

public synchronized int count() {

count++;

return count;

}

}

方案2:

class Counter{

private int count;

private Lock lock=new ReentrantLock();

public int count() {

lock.lock();

try {

count++;

return count;

}finally {

lock.unlock();

}

}

}

乐观锁实现计数器:

class Counter{

private AtomicInteger at=new AtomicInteger();

public int count() {

return at.incrementAndGet();

}

}

其中 AtomicInteger 是基于CAS算法实现。

如何理解线程的上下文切换?


一个线程得到CPU执行的时间是有限的。当此线程用完为其分配的CPU时间以后,cpu会切换到下一个线程执行。但是在这之前,线程需要将当前的状态进行保存,以便下次再次获得CPU时间片时可以加载对应的状态以继续执行剩下的任务。而这个切换过程是需要耗费时间的,会影响多线程程序的执行效率,所以在在使用多线程时要减少线程的频繁切换。那如何实现呢?

减少多线程上下文切换的方案如下:

  • 无锁并发编程:锁的竞争会带来线程上下文的切换

  • CAS算法:CAS算法在数据更新方面,可以达到锁的效果

  • 使用最少线程:避免不必要的线程等待

  • 使用协程:单线程完成多任务的调度和切换,避免多线程

如何理解死锁以及避免死锁问题?


多个线程互相等待已经被对方线程正在占用的锁,导致陷入彼此等待对方释放锁的状态,这个过程称之为死锁。

如何避免死锁呢?

  • 避免一个线程中同时获取多个锁

  • 避免一个线程在一个锁中获取其他的锁资源

  • 考虑使用定时锁来替换内部锁机制,如lock.tryLock(timeout)。

可能出现死锁的案例分享

class SyncThread implements Runnable {

private Object obj1;

private Object obj2;

public SyncThread(Object o1, Object o2) {

this.obj1 = o1;

this.obj2 = o2;

}

@Override

public void run() {

synchronized (obj1) {

work();

synchronized (obj2) {

work();

}

}

}

private void work() {

try {Thread.sleep(30000);} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

死锁测试

public class TestDeadLock01 {

public static void main(String[] args)throws Exception {

Object obj1 = new Object();

Object obj2 = new Object();

Thread t1 = new Thread(new SyncThread(obj1, obj2), “t1”);

Thread t2 = new Thread(new SyncThread(obj2, obj1), “t2”);

t1.start();

t2.start();

}

}

线程通讯与进程通讯应用增强

=======================================================================

如何理解进程与线程通讯?


  • 线程通讯:java中的多线程通讯主要是共享内存(变量)等方式。

  • 进程通讯:java中进程通讯(IPC)主要是Socket,MQ等。

在这里插入图片描述

如何实现进程内部线程之间的通讯?


基于wait/nofity/notifyall实现

wait()/notify()/notifyall()方法定义说明:

  • Wait:阻塞正在使用监视器对象的线程,同时释放监视器对象

  • notify: 唤醒在监视器对象上等待的单个线程,但不释放监视器对象,此时调用该方法的代码继续执行,直到执行结束才释放对象锁

  • notifyAll: 唤醒在监视器对象上等待的所有线程,但不释放监视器对象,此时调用该方法的代码继续执行,直到执行结束才释放对象锁

wait()/notify()/notifyall()方法应用说明

1) 这些方法必须应用在同步代码块或同步方法中

2) 这些方法必须由监视器对象(对象锁)调用

说明:使用wait/notify/notifyAll的作用一般是为了避免轮询带来的性能损失。

wait()/notify()/notifyall()应用案例实现:

手动实现阻塞式队列,并基于wait()/notifyAll()方法实现实现线程在队列上的通讯。

/**

  • 有界消息队列:用于存取消息

  • 1)数据结构:数组(线性结构)

  • 2)具体算法:FIFO(先进先出)-First in First out

*/

public class BlockContainer {//类泛型

/*用于存储数据的数组/

private Object[] array;

/*记录有效元素个数/

private int size;

public BlockContainer () {

this(16);//this(参数列表)表示调用本类指定参数的构造函数

}

public BlockContainer (int cap) {

array=new Object[cap];//每个元素默认值为null

}

}

向容器添加put方法,用于放数据。

/**

  • 生产者线程通过put方法向容器放数据

  • 数据永远放在size位置

  • 说明:实例方法内部的this永远指向

  • 调用此方法的当前对象(当前实例)

  • 注意:静态方法中没有this,this只能

  • 应用在实例方法,构造方法,实例代码块中

*/

public synchronized void put(T t){//同步锁:this

//1.判定容器是否已满,满了则等待

while(size==array.length)

try{this.wait();}catch(Exception e){}

//2.放数据

array[size]=t;

//3.有效元素个数加1

size++;

//4.通知消费者取数据

this.notifyAll();

}

向容器类添加take方法,用于从容器取数据。

/**

  • 消费者通过此方法取数据

  • 位置:永远取下标为0的位置的数据

  • @return

*/

@SuppressWarnings(“unchecked”)

public synchronized T take(){

//1.判定容器是否为空,空则等待

while(size==0)

try{this.wait();}catch(Exception e){}

//2.取数据

Object obj=array[0];

//3.移动元素

System.arraycopy(

array,//src 原数组

1, //srcPos 从哪个位置开始拷贝

array, //dest 放到哪个数组

0, //destPost 从哪个位置开始放

size-1);//拷贝几个

//4.有效元素个数减1

size–;

//5.将size位置为null

array[size]=null;

//6.通知生产者放数据

this.notifyAll();//通知具备相同锁对象正在wait线程

return (T)obj;

}

基于Condition实现

Condition 类定义说明

Condition 是一个用于多线程间协同的工具类,基于此类可以方便的对持有锁的线程进行阻塞或唤醒阻塞的线程。它的强大之处在于它可以为多个线程间建立不同的Condition,通过signal()/signalall()方法指定要唤醒的不同线程。

Condition 类应用说明

  1. 基于Lock对象获取Condition对象

  2. 基于Condition对象的await()/signal()/signalall()方法实现线程阻塞或唤醒。

Condition类对象的应用案例实现:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

由于细节内容实在太多了,为了不影响文章的观赏性,只截出了一部分知识点大致的介绍一下,每个小节点里面都有更细化的内容!

小编准备了一份Java进阶学习路线图(Xmind)以及来年金三银四必备的一份《Java面试必备指南》

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
-1713452093904)]

[外链图片转存中…(img-Da4qJICe-1713452093907)]

[外链图片转存中…(img-omCezxIs-1713452093909)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

由于细节内容实在太多了,为了不影响文章的观赏性,只截出了一部分知识点大致的介绍一下,每个小节点里面都有更细化的内容!

[外链图片转存中…(img-snP3bSpC-1713452093911)]

小编准备了一份Java进阶学习路线图(Xmind)以及来年金三银四必备的一份《Java面试必备指南》

[外链图片转存中…(img-GJzAraGj-1713452093912)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2401_84412895/article/details/137941004

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法