线程

线程安全的集合

五迷三道 提交于 2020-03-17 01:02:26
集合 #集合大概有4种类型:List Set Queue Map 其中Vector、HashTable、Properties是线程安全的。其中ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的。(线程不安全是指:当多个线程访问同一个集合或Map时,如果有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。) Collections提供多个获取线程安全的集合 CopyOnWriteArraylist #写有锁 读无锁的集合 加强版的读写分离 ); 其实现的原理为 : 写操作原理 :将底层的数组做了一次复制,写的是新数组 完成了赋值之后再讲新数组替换旧数组 每调用一次写 底层数组都会扩容一次 , 读操作原理 :读的是写操作完成之前的旧数组 ,写完成之后才能读到新数组的赋值。 CopyOnWriteArraySet( #序 无下标 元素不允许重复 线程安全的Set集合底层使用CopyOnWriteArraylist实现,不同的是在使用addIfAbsent() 添加元素,会遍历数组 ,如果有存在的元素则不添加 。 其实现的原理为 : 表面上使用add方法,底层使用的是CopyOnWriteArraylist的addIfAbsent() 来判断要插入的新值是否存在

9种 OOM 常见原因及解决方案

余生长醉 提交于 2020-03-16 21:46:54
当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误。本文总结了常见的 OOM 原因及其解决方法,如下图所示。如有遗漏或错误,欢迎补充指正。 1、Java heap space 当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出 java.lang.OutOfMemoryError:Javaheap space 错误(根据实际生产经验,可以对程序日志中的 OutOfMemoryError 配置关键字告警,一经发现,立即处理)。 原因分析 Javaheap space 错误产生的常见原因可以分为以下几类: 1、请求创建一个超大对象,通常是一个大数组。 2、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。 3、过度使用终结器(Finalizer),该对象没有立即被 GC。 4、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收。 解决方案 针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理: 1、如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。 2、如果是业务峰值压力

双亲委托模型的弊端以及线程上下文类加载器详解!

不问归期 提交于 2020-03-16 20:18:50
线程上下文类加载器的分析 双亲委托模型的弊端 我们先看一段我们非常熟悉的数据库连接相关的代码片段。 Class . forName ( "com.mysql.jdbc.Driver" ) ; Connection conn = DriverManager . getConnection ( "jdbc:mysql://localhost:3306/RUNOOB" , "root" , "123456" ) ; Statement stmt = conn . createStatement ( ) ; 如下图分析 案例分析 在上述图中的第五步为什么会用线程上下文加载器进行加载呢? 在双亲委托模型( 类加载器深入理解和双亲委托模型的案例分析 )的机制下,类的加载是由下而上的。即下次的加载器会委托上层进行加载。有些接口是Java核心库(rt.jar)提供的例如上面的createStatement接口,而Java核心库是由启动类加载器进行加载的。而这些接口的具体实现是来自不同的厂商(Mysql)。而具体的实现都是通过依赖jar包放到我们项目中的classPath下的。Java的启动类加载器/根类加载器是不会加载这些其他来源的jar包。 我们都知道classPath下的jar包是有我们系统类加载器/应用加载器进行加载,根据我们双亲委托的机制父类加载器是看不到子类(系统类加载器

JVM 基础(1) -- Java 的内存结构

只谈情不闲聊 提交于 2020-03-16 19:54:31
以黄小斜博文为主的学习总结 文章目录 1. 了解 JVM 内存有什么好处 2. JVM 主要组成部分 3. 运行时数据区的五大组成部分 1. 程序计数器 2. Java 虚拟机栈 3. 本地方法栈 4. Java 堆 5. 方法区 4. 控制各区域大小的参数 1. 了解 JVM 内存有什么好处 所有的 Java 开发人员可能会遇到这样的困惑:我该为堆内存设置多大空间呢?OutOfMemoryError 的异常到底涉及到运行时数据区的哪块区域?该怎么解决呢? 其实如果你经常解决服务器性能问题,那么这些问题就会变的非常常见,了解 JVM 内存可以帮助我们在服务器出现性能问题的时候,快速的了解哪块内存区域出现了问题,以便快速的解决生产故障。 2. JVM 主要组成部分 JVM 主要由 类加载器 、运行时数据区 、执行引擎和本地库接口四部分组成。 JVM 工作的流程大致就是:首先由类加载器将我们的 .class 文件加载进运行时数据区,然后 JVM 会在堆中创建一个对应类的 Class 对象,但由于我们的字节码只是 JVM 的一套指令集规范,并不能直接交给底层的操作系统去执行,所以这里就需要用到特定的字节码解析器执行引擎将我们的字节码解析成底层操作系统可以执行的机器指令,然后交由 CPU 去执行,在执行的过程中可能还需要用到其他语言的本地库接口进而完成整个程序的功能。 3.

线程同步和互斥的关系

时间秒杀一切 提交于 2020-03-16 19:46:18
互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。 同步其实已经实现了互斥,所以同步是一种更为复杂的互斥。 互斥是一种特殊的同步。 所谓互斥,就是不同线程通过竞争进入临界区(共享的数据和硬件资源),为了防止访问冲突,在有限的时间内只允许其中之一独占性的使用共享资源。如不允许同时写 同步关系则是多个线程彼此合作,通过一定的逻辑关系来共同完成一个任务。一般来说,同步关系中往往包含互斥,同时对临界区的资源会按照某种逻辑顺序进行访问。如先生产后使用 总的来说,两者的区别就是: 互斥是通过竞争对资源的独占使用,彼此之间不需要知道对方的存在,执行顺序是一个乱序。 同步是协调多个相互关联线程合作完成任务,彼此之间知道对方存在,执行顺序往往是有序的。 lock与unlock方法,替换synchronized,这就是互斥锁的体现。消费者生产者模式就是同步锁的体现。 转载:http://www.cnblogs.com/baizhanshi/p/6844356.html 互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 同步是指在互斥的基础上(大多数情况)

go语言之Goroutines

时间秒杀一切 提交于 2020-03-16 17:55:15
说明 计算机每开启一个程序,都会开启一个进程,而每一个进程当中也同样会包含很多的子任务,这些任务会通过线程来分化完成,但是线程在切换的时候存在上下文切换消耗,这个时候就轮到协程登场了。 首先,我们要知道的是,协程是属于线程的,也就是说协程是在线程中跑的,因此协程用被称为微线程。因为协程需要手动切换所以更加的灵活被称为用户线程空间。 而在go中,天生就带有了goroutine,能够帮助我们完成并发操作,这也是go能够流行的原因。 Goroutines 是在 Golang 中执行并发任务的方式。它们仅存在于 Go 运行时的虚拟空间中而不存在于 OS 中,因此需要 Go 调度器来管理它们的生命周期。请记住这一点很重要,对于所有操作系统看到的都只有一个请求并运行多个线程的单个用户级进程。goroutine 本身由 GoRuntimeScheduler 管理。 关于goroutine的详细原理,可以去读一下go语言实战。 使用 在Go语言中,每一个并发的执行单元叫作一个goroutine。设想这里的一个程序有两个函数,一个函数做计算,另一个输出结果,假设两个函数没有相互之间的调用关系。一个线性的程序会先调用其中的一个函数,然后再调用另一个。如果程序中包含多个goroutine,对两个函数的调用则可能发生在同一时刻。马上就会看到这样的一个程序。 当一个程序启动时

阿里P8架构师谈:Java并发编程实战

谁说我不能喝 提交于 2020-03-16 17:34:34
本人免费整理了Java高级资料,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高并发分布式等教程,一共30G,需要自己领取。 传送门: https://mp.weixin.qq.com/s/osB-BOl6W-ZLTSttTkqMPQ 前言 并发编程是Java语言的重要特性之一, 在Java平台上提供了许多基本的并发功能来辅助开发多线程应用程序。然而,这些相对底层的并发功能与上层应用程序的并发语义之间并不存在一种简单而直观的映射关系。因此,如何在Java并发应用程序中正确且高效地使用这些功能就成了Java开发人员的关注重点。 本书介绍 全书内容由浅入深,共分为四个部分。第一部分介绍了Java并发编程的基础理论,包括线程安全性与状态对象的基础知识,如何构造线程安全的类并将多个小型的线程安全类构建成更大型的线程安全类,以及Java平台库中的一些基础并发模块:第二部分介绍了并发应用程序的构造理论,包括应用程序中并行语义的分解及其与逻辑任务的映射,任务的取消与关闭等行为的实现,以及Java线程池中的一些高级功能,此外还介绍了如何提高GUI应用程序的响应性:第三部分介绍了并发编程的性能调优,包括如何避免活跃性问题,如何提高并发代码的性能和可伸缩性以获得理想的性能,以及在测试并发代码正确性和性能时的一些实用技术

windows多线程同步--临界区

浪子不回头ぞ 提交于 2020-03-16 14:33:30
推荐参考博客: 秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念 ,一般操作系统书上面都有。 适用范围:它只能同步一个进程中的线程,不能跨进程同步。一般用它来做单个进程内的代码快同步,效率比较高 windows中与临界区有关的结构是 CRITICAL_SECTION,关于该结构体的内部结构可参考 here 使用时,主线程中要先初始化临界区,最后要删除临界区,具体使用见下面代码: 本文地址 从一个例子来说明:假设有三个线程都需要使用打印机,我们可以把打印的代码放到临界区,这样就可以保证每次只有一个线程在使用打印机。 #include<string> #include<iostream> #include<process.h> #include<windows.h> using namespace std; //定义一个临界区 CRITICAL_SECTION g_cs; //线程绑定的函数返回值和参数是确定的,而且一定要__stdcall unsigned __stdcall threadFun(void *param) { EnterCriticalSection(&g_cs);//进入临界区,如果有其他线程则等待 cout<<*(string *)(param)<<endl; LeaveCriticalSection(&g_cs);//退出临界区,其他线程可以进来了

进程&线程 同步异步&阻塞非阻塞

六月ゝ 毕业季﹏ 提交于 2020-03-16 14:27:49
2015-08-19 15:23:38 周三 线程 线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码 线程安全问题都是由全局变量及静态变量引起的 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据 一条线程指的是进程中一个单一顺序的 控制流 ,一个进程中可以并行多个线程,每条线程并行执行不同的任务 线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文 join();可以用来邀请其他线程先执行 yield();告诉系统"把自己的CPU时间让掉,让其他线程或者自己运行" 同步异步&阻塞非阻塞 1. 同步,就是我调用一个功能,该功能没有结束前,我死等结果。 2. 异步,就是 我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知) 3. 阻塞, 就是调用我(函数),我 (函数)没有接收完数据或者没有得到结果之前

java 集合(list、set、map)的特点

六月ゝ 毕业季﹏ 提交于 2020-03-16 14:12:37
集合相关的类有一大堆,一般也只用到常用的方法增删改查,而且它它们的方法名也基本一样,所以一直都不知道什么时候用什么集合, 今天趁有空特意从网上整理资料方便日后回忆。 一、List:、有顺序以线性方式存储,可以存放重复对象 线程安全方法:List list = Collections.synchronizedList(new LinkedList(...)); LinkedList:双向链表实现存储  索引数据慢插入数度较快  线程不安全(比安全性能好) ArrayList:数组方式存储数据  索引数据快插入数据慢  线程不安全 Vector:数组方式存储数据  索引数据快插入数据慢  线程安全 Stack:继承自 Vector ,实现一个后进先出的堆栈 二、Set:无顺序,不包含重复的元素 HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。 TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。 LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。 三、Map:键必须是唯一 同步方法:Map m = Collections.synchronizedMap(new TreeMap(...));