java并发编程小结
旭日Follow_24 的CSDN 博客 ,全文地址请点击:
https://blog.csdn.net/xuri24/article/details/82078467
线程简介:
线程是操作系统调度的最先单元,进程:线程=1:N 关系,也就是说一个进程可以创建多个线程,至少包含一个线程。多线程可以最大限度的使用CPU和维护各线程之间的并发进行关系等。
一、concurrent并发包
- locks部分:显式锁(互斥锁和速写锁)相关;
- atomic部分:原子变量类相关,是构建非阻塞算法的基础;
- executor部分:线程池相关;
- collections部分:并发容器相关;
- tools部分:同步工具相关,如信号量、闭锁、栅栏等功能;
二、volatile变量
volatile为声明共享变量提供了读/写操作同步,即多个线程同时对变量进行读写操作,每次线程操作的变量值都将会是最新的那个值。例如:A线程对变量进行写操作,同时B线程对变量进行读操作,传统的方式操作会出现脏读(即B线程读到不是A线程更新的值),使用volatile声明该变量后,B线程读到的将是A线程更新后提交到主内存中最新的值。
三、syncronized同步变量
syncronized是同步关键字,并发编程中一个重要的关键字属性。
- 对于普通同步方法,锁是当前实例对象
- 对于静态同步方法,锁是当前类的Class对象
- 对于同步方法块,锁是Syncronized括号里配置的对象
当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时候,必须释放锁。
四、lock锁
Lock接口,锁用来控制多个线程访问共享资源的方式,一个锁能够防止多个线程同时访问共享资源(读写锁例外)。与syncronized不同的是,lock是显式的获取和释放锁,syncronized是隐式的jvm内置的关键字。
- void lock() 获取锁方法
- lockInterruptibly()throws interruptedException 可中断地获取锁,与lock不同的是,该方法在获取的过程中可中断线程
- boolean tryLock() 尝试非阻塞的获取锁,获取到返回true,否则返回false
- boolean tryLock(long time,TimeUnit unit)throws InterruptedException 超时获取锁,3种情况返回:1、当前线程在超时时间内获得了锁 2、当前线程在超时时间内被中断 3、超时时间结束,返回false
- void unlock() 释放锁方法
- Condition newCondition() 获取等待通知组件,该组件和当前的锁绑定,当前线程只有获得了锁,才能调用该组件的wait()方法,调用后当前线程释放锁
队列同步器AbstractQueuedSynchronizer(AQS),用来构建锁或其他同步组件的基础框架,使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
- getState() 获取当前同步状态
- setState(int newState) 设置当前同步状态
- compareAndSetState(int expect,int update) 使用CAS设置当前状态,该方法能够保证状态设置的原子性
重入锁ReentrantLock,支持一个线程对资源的重复加锁,支持获取锁的公平和非公平性选择。
- 实现重进入
- 线程再次获取锁
- 锁的最终释放
- 公平和非公平获取锁
- 读写所
- LockSupport工具
- Condition接口
五、java并发容器和框架
ConcurrentHashMap线程安全且高效的HashMap。并发编程中HashMap可能会导致线程死循环,HashTable效率又非常低下。
HashMap中的put操作,Entry链表会形成环形数据结构后,Entry的next节点将永远不为空,则产生死循环。
ConcurrentHashMap是由:Segment数组结构和HashEntry数组结构组成,Segment是一种可重入锁(ReentrantLock),HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含了一个Segment数组,一个Segment里包含了一个HashEntry数组,每个Segment守护着HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获取它对应的Segment锁。
六、Java线程池
线程池多用于并发框架,线程池的好处:
- 降低资源消耗
- 提高相应速度
- 提高线程的可管理性
实现原理,线程池的处理流程:
- 线程池判断核心线程里的线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务,如果核心线程池里的线程都在执行任务,则进入下个流程。
- 线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里,如果工作队列满了,则进入下个流程。
- 线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
线程池的使用:
- 创建线程池ThreadPoolExecutor new ThreadPoolExecutor(corePoolsize ,maximumPoolSize,keepAliveTime,milliseconds,runnableTaskQueue,handler);
- corePoolsize 线程池的基本大小,提交一个任务到线程池后,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建。
- runnableTaskQueue 任务队列,用于保存等待执行的任务的阻塞队列
- maximumPoolSize 线程池最大的数量,允许创建的最大线程数,如果队列已满,并且以创建的线程数小于最大线程数,则线程池会再创建新的线程来执行任务。
- keepAliveTime 线程活动保持时间,线程池工作线程空闲后,保持存活的时间。
- handler 饱和策略,当队列和线程池都满了,则线程池处于饱和状态,必须采取策略来处理提交的新任务:抛异常、只用调用者的所在线程来运行任务、丢弃队列里最近一个任务,执行当前任务、不处理,直接丢弃。
2.向线程池提交任务
3.关闭线程池
4.配置线程池
5.线程池的监控
七、Executor框架
Executor框架的常用的几个接口和子类

Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),
ExecutorService:是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行状况返回Future的方法
AbstractExecutorService:ExecutorService执行方法的默认实现
ScheduledExecutorService:一个可定时调度任务的接口
ScheduledThreadPoolExecutor:ScheduledExecutorService的实现,一个可定时调度任务的线程池
ThreadPoolExecutor:线程池,可以通过调用Executors以下静态工厂方法来创建线程池并返回一个ExecutorService对象
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) //后两个参数为可选参数
参数说明:
corePoolSize:核心线程数,如果运行的线程少于corePoolSize,则创建新线程来执行新任务,即使线程池中的其他线程是空闲的
maximumPoolSize:最大线程数,可允许创建的线程数,corePoolSize和maximumPoolSize设置的边界自动调整池大小:
corePoolSize <运行的线程数< maximumPoolSize:仅当队列满时才创建新线程
corePoolSize=运行的线程数= maximumPoolSize:创建固定大小的线程池
keepAliveTime:如果线程数多于corePoolSize,则这些多余的线程的空闲时间超过keepAliveTime时将被终止
unit:keepAliveTime参数的时间单位
workQueue:保存任务的阻塞队列,与线程池的大小有关:
当运行的线程数少于corePoolSize时,在有新任务时直接创建新线程来执行任务而无需再进队列
当运行的线程数等于或多于corePoolSize,在有新任务添加时则选加入队列,不直接创建线程
当队列满时,在有新任务时就创建新线程
threadFactory:使用ThreadFactory创建新线程,默认使用defaultThreadFactory创建线程
handle:定义处理被拒绝任务的策略,默认使用ThreadPoolExecutor.AbortPolicy,任务被拒绝时将抛出RejectExecutorException
java并发编程小结的更多相关文章
- 那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
<Java并发编程实战>和<Java并发编程的艺术> Executor框架小结 1.在线程中如何执行任务 (1)任务执行目标: 在正常负载情况下,服务器应用 ...
- JAVA并发编程J.U.C学习总结
前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...
- java并发编程实战学习(3)--基础构建模块
转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put ...
- Java并发编程——BlockingQueue
简介 BlockingQueue很好的解决了多线程中,如何高效安全"传输"数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利. 阻塞队列是 ...
- [Java并发编程(四)] Java volatile 的理论实践
[Java并发编程(四)] Java volatile 的理论实践 摘要 Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 ...
- Java并发编程-核心问题(1)
一.常见问题 从小的方面讲, 并发编程最常见的问题就是可见性.原子性和有序性问题. 从大的方面讲, 并发编程最常见的问题就是安全性问题.活跃性问题和性能问题. 下面主要从微观上分析问题. 二.可见性问 ...
- Java并发编程原理与实战四十二:锁与volatile的内存语义
锁与volatile的内存语义 1.锁的内存语义 2.volatile内存语义 3.synchronized内存语义 4.Lock与synchronized的区别 5.ReentrantLock源码实 ...
- Java并发编程——阻塞队列BlockingQueue
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- 读《Java并发编程的艺术》学习笔记(一)
接下来一个系列,是关于<Java并发编程的艺术>这本书的读书笔记以及相关知识点,主要是为了方便日后多次复习和防止忘记.废话不多说,直接步入主题: 第1章 并发编程的挑战 并发编程的目的是 ...
随机推荐
- 给你的WordPress站点添加下雪特效
今天看到这个教程,感觉挺应景的,就自己尝试了下,效果还行,没截GIF图 方法: 该js文件已支持https,同时已将其及相关雪花图片进行CDN加速处理,可直接调用. 找到WordPress主题的foo ...
- 一键访问Google和YouTube等国外知名网站
1.首先打开快速安全通道网站,点击注册!网站地址 https://www.faststunnel.xyz/GWx6uy0M 2.注册好之后下载插件 3.将插件下载完后拖到浏览器安装 4.登录插件,即可 ...
- Javascript高级编程学习笔记(63)—— 事件(7)鼠标及滚轮事件
鼠标与滚轮事件 鼠标事件是web开发中最常用的一类事件,毕竟鼠标是最主要的定位设备 DOM3级事件中定义了9个鼠标事件: click:在用户单击主鼠标按钮(一般为鼠标左键)或者按下回车时触发,这一点对 ...
- 8.快速索引、listview
实现这样的效果 布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...
- 3D轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C 单向链表的创建、插入及删除
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用.链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节 ...
- 一个简单的实例演示vuex模块化和命名空间
因为Vuex Store是全局注册的,不利于较大的项目,引入模块分离业务状态和方法,引入命名空间解决不同模块内(getters,mutaions,actions)名称冲突的问题 ----------- ...
- Spring详解(六)------AspectJ 实现AOP
上一篇博客我们引出了 AOP 的概念,以及 AOP 的具体实现方式.但是为什么要这样实现?以及提出的切入点表达式到底该怎么理解? 这篇博客我们通过对 AspectJ 框架的介绍来详细了解. 1.什么是 ...
- 什么 是JavaScript中的字符串类型之间的转换问题详解? 部分4
字符串类型 单双引号都可以!建议使用单引号!(本人建议:个人觉得单个字符串更利于网页优化@特别地方特别处理!); 判断字符串的长度获取方式:变量名.length html中转义符: < < ...
- 今日头条面试题——LRU原理和Redis实现
很久前参加过今日头条的面试,遇到一个题,目前半部分是如何实现 LRU,后半部分是 Redis 中如何实现 LRU. 我的第一反应应该是内存不够的场景下,淘汰旧内容的策略.LRU ... Least R ...