图学java基础篇之并发
概述
并发处理本身就是编程开发重点之一,同时内容也很繁杂,从底层指令处理到上层应用开发都要涉及,也是最容易出问题的地方。这块知识也是评价一个开发人员水平的重要指标,本人自认为现在也只是学其皮毛,因此本文重点介绍java的并发相关体系,具体的点懂得就多讲,不懂得就给出参考文章。先来看图:
本文重点介绍jdk中concurrent的内容,并发相关基础不在介绍,如果想系统的学习,建议直接看并发大作《java并发编程实践》吧(之前看过,可惜很多地方没懂),博客终究只是快餐,增强学习拓展知识很好,但打基础还是要看书实战的。
java内存模型
直接盗图一张(图寝删),详细讲解参考博客。
java内存模型的作用可以理解为抽象了线程私有内存与主存(共享内存或堆)的关系,也就是原子性、可见性、顺序性的原则,而后介绍的内容都是为了保证这些原则的实现手段。
实现多线程的方法
这一块其实不必多说,大家都很熟悉,这里简单对比下优缺点:
- 继承Thread:由于java不支持多继承,所以用起来有很强的局限性,使用场景不多。
- 实现Runnable接口:常用的方式,有点对比Thread,并且更方便实现资源共享(两者异同,重点在评论)
- 实现Callable接口: 结合Future使用,可以获取线程执行结果
- Executor:concurrent中提供的一个上层并发处理框架,底层也是基于上边三种实现,基于此实现了线程池、任务调度等类,为一些典型场景提供了便捷的实现手段。
实现同步的方法
这一块也是常用的,也仅对比介绍一下:
- volatile:volatile保证了原子操作在线程间的可见性(注意仅能保证可见性),并且修饰对象的操作不会指令重排。对于一个原子操作可以保证其之间一致,但是原子操作真的很少,比如i++都不行。更多介绍
- Atomic:原子类,,基于CAS原理实现,提供了基本类型和引用对应的类,能保证其基本操作的可见性,底层基于volatile和Unsafe类(一个线程安全相关类,可以调用底层native方法)。如果线程间的同步仅限于某个值的改变,则可考虑用该类(实际上多数时候即使适合用也能找到对应的上层封装类,而不必自己实现)
- synchronized:最为常用的同步方法之一,可以分为同步方法和同步代码块两类,使用简单,唯一一定要搞清的是synchronized锁的对象是谁。(拓展:synchronized底层实现)
- wait/notify:同步几大原语之二(记得还有join吧),java的Object中已实现的native方法,常用来同步线程执行顺序或进度,然而多数场景concurrent也提供了对应工具类,所以一般使用时也应该优先使用对应的工具类
- Lock:锁,主要有ReentrantLock和ReadWriteLock,该方式较synchronized的优势就是使用比较灵活,同步不再局限于代码块或者方法,可以在任何需要的地方加锁解锁。就性能方面,除非你用的是1.4之前的jdk,否则两者差异不大
- ThreadLocal:线程本地变量,其内部是一个map,key为线程对象本身,value为对应变量的一个拷贝,每个线程使用该变量时实际使用的是其副本,以此解决多线程共享变量的竞争,需要注意的是改类型并不是解决同步问题的,而是解决资源共享问题的,每个线程使用各自的副本,相互之间不影响,但是该变量的值变化相互之间也是隔离的ThreadLocal深入剖析
concurrent包
JDK 1.5增加了java.util.concurrent包,其内部提供了大量并发相关类,大大简化了设计并发的程序开发。该包大致可分为四大块:Atomic、Lock、Executor、以及线程安全的集合类,由于集合类已经在该系列第一篇介绍过,因此这里重点介绍前三块,此外还有一些工具类,这里仅介绍几个常见的。
Atomic
前边已经介绍过,Atomic为修饰的对象提供了原子更新,保证了其更新在线程间的可见性,Atomic包内的原子类实现主要基于CAS原理,利用了Unsafe包提供的CAS方法,其中可以分为以下几类:
- 原子更新基本类型类,提供了AtomicBoolean、AtomicInteger和AtomicLong,对于其他基本类型,可以参照其实现自行通过Unsafe的方法实现(实质上都是转成int处理)
- 原子更新数组类:也提供了三种类型:AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray
- 原子更新引用类型:对于非基本类型提供的类,AtomicReference、AtomicReferenceFieldUpdater、AtomicMarkableReference
- 原子更新字段类:这几个类主要用于更新类中的某个字段:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference
这些类使用方法类似,都是通过以下方法实现原子更新: - getAndSet(v):设置新值,返回旧值
- compareAndSet(expectedValue, newValue):如果当前值(current value)等于期待的值(expectedValue), 则原子地更新指定值为新值(newValue), 如果更新成功,返回true, 否则返回false, 换句话可以这样说: 将原子变量设置为新的值, 但是如果从我上次看到的这个变量之后到现在被其他线程修改了(和我期望看到的值不符), 那么更新失败
详细的使用可以参考Java中的Atomic包使用指南
Lock
Lock提供了一种更为灵活的同步方式,Lock下主要有以下类:
- ReentrantLock:重入锁,其底层通过一个Sync的静态类实现加锁解锁。Sync继承自AbstractQueuedSynchronizer,该抽象类内部实现了一个链表,保存了请求获取锁的状态,同时其内部有一个状态值,用来表示锁是否被线程获取,其修改通过Unsafe包提供的CAS方法,以此可以保证其可见性。同时尤其内部实现也可以知道,之所以叫重入锁,是因为其提供了非阻塞的使用方式,如果使用tryLock方法,当lock时在发现锁已lock的情况下,会立即返回结果,而不会阻塞。使用示例
- ReentrantReadWriteLock:可重入读写锁。实现原理和ReentrantLock一样,再次基础上增加了读写锁的操作。使用示例
- Condition:实现类是AbstractQueuedSynchronizer中的一个内部类,其功能是实现线程间的协调通信,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁。使用示例
- LockSupport:可以看做对Unsafe包中并发原语的封装,为上层的锁实现提供原语操作。一般情况下上层开发很少用到。
Executor
Executor框架是concurrent中最常用的内容之一,其提供了一套能够便捷管理线程和任务的类,使我们能够很方便创建、调度一批具有同类操作的线程。其主要有以下几个类(接口):
- Callable、Future:前边已经介绍过了,提供了一种可以获取返回值的线程实现方法,一般与
ExecutorService配合使用。Callable使用 - Executor:线程工具类,主要用于线程池、ThreadFactory、Callable实例。Executors详解
- ThreadFactory:接口类,提供了创建线程个工厂类,多是时候配合线程池,作为参数传入为线程池提供创建线程的方法。
- ExecutorService:接口类,是线程池实现类ThreadPoolExecutor的基类。
- ExecutorCompletionService:与ExecutorService功能一样,不过其提供了poll()和take()两个方法用于获取线程执行结果,前者是非阻塞的,后者是阻塞的。
使用示例
other
此外concurrent包还提供了一些其他类,这里仅列出功能,具体的使用可自行查询,这里给出一个比较完善的总结java.util.concurrent 用户指南
- ForkJoinPool:和ExecutorService类似,不过其提供了fork和join的功能,能够将池内指定级别的任务进行分解或合并。这种处理方式与目前很多流处理框架类似,不过该实现使用的不多。
- CountDownLatch:CountDownLatch 是一个线程协调器,它允许一个或多个线程等待一系列指定操作的完成。
CountDownLatch 以一个给定的数量初始化。countDown() 每被调用一次,这一数量就减一。通过调用await() 方法之一,线程可以阻塞等待这一数量到达零。 - CyclicBarrier:CyclicBarrier类也是一种同步机制,它可以在指定位置设定barrier,只有所有线程都执行到该位置是,才会继续向下执行。
- Exchanger:该类提供了线程间交换数据的方法,可以视作一个管道。实现原理
- Semaphore:信号量,学过操作系统的都知道,实现生产者—消费者的常用手段之一,信号量最大的用处是可以控制资源的访问数量,比起阻塞队列更加灵活。使用示例
其他
正如最开始所说的,并发相关的知识绝不是看一些知识点就可以掌握的,如果想要真正掌握,必须系统的学习。这里只是列出一些java相关的知识点,仅供参考。
最后再附两篇博文,有兴趣的可以看下:
图学java基础篇之并发的更多相关文章
- 图学java基础篇之IO
java io体系 如图可以看出,java的io按照包来划分的话可以分为三大块:io.nio.aio,但是从使用角度来看,这三块其实揉杂在一起的,下边我们先来概述下这三块: io:主要包含字符流和字节 ...
- 图学java基础篇之集合
(本文部分图片引用自其他博客,最后有链接,侵删.由于笔记使用markdown记录,格式可能不是太好看,见谅) 集合结构 红字为java.util包下的,绿字为concurrent包下扩展的与并发相关的 ...
- 图学java基础篇之集合工具
两个工具类 java.utils下又两个集合相关_(准确来说其中一个是数组的)_的工具类:Arrays和Collections,其中提供了很多针对集合的操作,其中涵盖了一下几个方面: 拷贝.填充.反转 ...
- 金三银四跳槽季,BAT美团滴滴java面试大纲(带答案版)之一:Java基础篇
Java基础篇: 题记:本系列文章,会尽量模拟面试现场对话情景, 用口语而非书面语 ,采用问答形式来展现.另外每一个问题都附上“延伸”,这部分内容是帮助小伙伴们更深的理解一些底层细节的补充,在面试中可 ...
- 小白—职场之Java基础篇
java基础篇 java基础 目录 1.java是一种什么语言,jdk,jre,jvm三者的区别 2.java 1.5之后的三大版本 3.java跨平台及其原理 4.java 语言的特点 5.什么是字 ...
- Java基础篇(JVM)——类加载机制
这是Java基础篇(JVM)的第二篇文章,紧接着上一篇字节码详解,这篇我们来详解Java的类加载机制,也就是如何把字节码代表的类信息加载进入内存中. 我们知道,不管是根据类新建对象,还是直接使用类变量 ...
- java基础篇---I/O技术
java基础篇---I/O技术 对于任何程序设计语言而言,输入输出(I/O)系统都是比较复杂的而且还是比较核心的.在java.io.包中提供了相关的API. java中流的概念划分 流的方向: 输 ...
- java基础篇---HTTP协议
java基础篇---HTTP协议 HTTP协议一直是自己的薄弱点,也没抽太多时间去看这方面的内容,今天兴致来了就在网上搜了下关于http协议,发现有园友写了一篇非常好的博文,博文地址:(http: ...
- java基础篇---I/O技术(三)
接上一篇java基础篇---I/O技术(二) Java对象的序列化和反序列化 什么叫对象的序列化和反序列化 要想完成对象的输入或输出,还必须依靠对象输出流(ObjectOutputStream)和对象 ...
随机推荐
- IIS错误HTTP 错误 500.21 - Internal Server Error
原因:在安装Framework v4.0之后,再启用IIS,导致Framework没有完全安装 解决:以管理员身份运行cmd->输入“%windir%\Microsoft.NET\Framewo ...
- 为什么要使用Vuex?
为什么要使用Vuex? 1. 假如不使用 1.1 父子组件依赖同一个state 1.2 兄弟组件依赖同一个state 2. 用了Vuex之后 3. 方便记忆和理解
- Jackson使用手册
引用jar:jackson-core,jackson-databind,jackson-annotations http://central.maven.org/maven2/com/fasterxm ...
- Servlet和JavaBean
1.Servlet简介: Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间 ...
- CAD Import .NET支持AutoCAD DWG 2013
CADSoftTools发布了CAD Import .NET 9一个新版本.NET开发库,可以提供给开发人员导入AutoCAD DWG.DXF.HPGL.PLT.CGM等格式的功能. 在新版本中,CA ...
- Eucalyptus-instance启动后查看运行状态
1.前言 在eucalyptus中通过虚拟机模板,创建并启动一个虚拟机,这个时候虚拟机启动正常,但是外部一直无法访问也ping不通,正对这种情况我们如何检查排除问题呢? 两种检查问题的方法: 1).在 ...
- 一、基于Qt的图像矩形区域改色
Qt环境下图像的打开和涂色 一.设计目标 能够在 Qt QtCreator 环境下打开常用图像格式文件,诸如 bmp.jpg.png 图像等,然后将他们转化为 Qt 中的 QImage 类,并进行矩形 ...
- matplotlib学习之(四)设置线条颜色、形状
本文是学习<matplotlib for python developers>的一点笔记plot画图时可以设定线条参数.包括:颜色.线型.标记风格.1)控制颜色颜色之间的对应关系为b--- ...
- java poi读取excel公式,返回计算值(转)
http://blog.csdn.net/CYZERO/article/details/6573015 经测试,确实可以 1 package hrds.zpf.poi; 2 3 import o ...
- 2017.12.25 Java中面向对象思想的深刻理解
今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 * A: 面向过程与面 ...