李孟聊人工智能
独立开源软件开发者,SolidUI作者。老程序员,老扑街作者,依然奋战在开源一线,依然继续写文章。
展开
-
Java并发实战汇总
一.并发理论基础并发编程Bug源头:https://limeng.blog.csdn.net/article/details/109020395Java内存模型(解决可见性和有序性问题):https://limeng.blog.csdn.net/article/details/109262247互斥锁:https://limeng.blog.csdn.net/article/details/109551131死锁:https://limeng.blog.csdn.net/article/detai原创 2020-12-31 17:12:54 · 715 阅读 · 1 评论 -
Java并发ForkJoin
文章目录一.简介二.Fork/Join2.1 分治任务模型2.2 API2.3 ForkJoinPool 工作原理三.示例一.简介并发编程可以分为三个层面的问题,分别是分工、协作和互斥,用类比现实世界的一些情况去理解并发任务,可以把线程池、Future、CompletableFuture 和 CompletionService 都列到了分工里面。还有一种“分治”的任务模型,指的是把一个复杂的问题分解成多个相似的子问题,然后再把子问题分解成更小的子问题,直到子问题简单到可以直接求解。分治思想在很多领域原创 2020-12-31 17:01:32 · 464 阅读 · 1 评论 -
Java并发CompletionService
一.简介CompletionService的应用场景:批量提交异步任务。CompletionService将线程池Executor和阻塞队列BlockingQueue融合在一起,使得批量异步任务的管理更简单。CompletionService能够让异步任务的执行结果有序化,先执行完的先进入阻塞队列,避免无谓的等待。二.API接口public interface CompletionService<V> {// 提交Callable类型的任务Future<V>原创 2020-12-29 21:18:31 · 414 阅读 · 1 评论 -
Java并发CompletableFuture
文章目录一.简介二.API2.1 创建CompletableFuture对象2.2 CompletionStage2.3 异常处理三.示例一.简介异步化,是以并行方案得以实施的基础,更深入地讲其实就是:利用多线程优化性能这个核心方案得以实施的基础。CompletableFuture 满足一些简单的异步编程需求。二.API2.1 创建CompletableFuture对象public static CompletableFuture<Void> runAsync(Runnable r原创 2020-12-27 21:10:23 · 530 阅读 · 0 评论 -
Java并发Future
一.简介ThreadPoolExecutor线程池获取任务执行结果,用到Future可以实现。二.获取执行结果Java通过ThreadPoolExecutor 提供3个submit()方法和1个FutureTask 工具类来支持获得任务执行结果的需求。// 提交Runnable任务Future<?> submit(Runnable task);// 提交Callable任务<T> Future<T> submit(Callab原创 2020-12-19 16:05:04 · 518 阅读 · 1 评论 -
Executor与线程池
文章目录一.简介二.线程池2.1 简介2.2 使用Java中线程池2.3 注意一.简介创建对象,仅仅是在JVM的堆里分配一块内存而已;而创建一个线程,却需要操作系统内核的API,然后操作系统要为线程分配一系列的资源,这个成本很高了,所以线程是一个重量级的对象,应该避免频繁创建和销毁。一般池化思想线程池和一般意义的池化资源是不同,一般意义的池化资源,都是需要资源的时候就调用 acquire() 方法来申请资源,用完之后就调用 release() 释放资源。若你带着这个固有模型来看并发包里线程池相关原创 2020-12-05 21:16:42 · 539 阅读 · 0 评论 -
并发容器
文章目录一.同步容器二.并发容器2.1 List2.2 Map2.3 Set2.4 Queue一.同步容器Java中的容器主要可以分为四大类,分别是List、Map、Set和Queue,但并不是所有的Java容器都是线程安全的,例如:我们常用的ArrayList、HashMap就不是线程安全。保证容器线程安全方法把非线程安全的容器封装在对象内部,控制访问路径。SafeArrayList<T>{ //封装ArrayList List<T> c = new Arra原创 2020-11-29 15:04:26 · 634 阅读 · 1 评论 -
无锁工具类
文章目录一.示例二.无锁方案实现原理三.原子类3.1 原子化的基本数据类型3.2 原子化的对象引用类型3.3 原子化数组3.4 原子化对象属性更新器3.5 原子化的累加器一.示例累加器示例。public class Test { AtomicLong count = new AtomicLong(0); void add10K() { int idx = 0; while(idx++ < 10000) { count.getAndIncrement(原创 2020-11-23 20:52:42 · 648 阅读 · 0 评论 -
Java并发CountDownLatch和CyclicBarrier
文章目录一.简介二.CountDownLatch三.CyclicBarrier四.总结一.简介CountDownLatch和CyclicBarrier是jdk concurrent包下工具类,提供一种控制并发流程的工具。二.CountDownLatch构造类,常用apipublic CountDownLatch(int count) { }; //参数count为计数值public void await() throws InterruptedException { }; //调用awa原创 2020-11-19 12:05:49 · 469 阅读 · 0 评论 -
Java并发StampedLock
文章目录一.简介二.锁模式三.总结一.简介读写锁(ReadWriteLock)允许多个线程同时读共享变量,适用于读多写少的场景,读多写少场景中比这更快的方案就是StampedLock,比读写锁性能好。二.锁模式ReadWriteLock支持两种模式:一种是读锁,一种是写锁,而StampedLock支持三种模式,分别:写锁、悲观读锁和乐观读。其中,写锁、悲观读锁的语义和ReadWriteLock的写锁、读锁的语义非常类似,允许多个线程同时同时获取悲观读锁,但是只允许一个线程获取写锁,写锁和悲观读锁是互原创 2020-11-18 23:57:31 · 570 阅读 · 0 评论 -
Java线程池
一.简介线程池(Thread Pool)是一种基于池化思想的管理线程的工具,经常出现在多线程服务器中,如MySQL。线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。优势降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。提高响应速度:任原创 2020-09-24 21:05:33 · 2819 阅读 · 4 评论 -
Java并发ReadWriteLock
文章目录一.简介二.读写锁三.示例-缓存一.简介读多写少场景,实际工作中,为了优化性能,我们经常会使用缓存,例如缓存元数据、缓存基础数据等,这就是一种典型的读多写少应用场景,缓存之所以能提升性能,一个重要的条件就是缓存的数据一定是读多写少的,例如元数据和基础数据基本上不会发生变化(写少),使用它们的地方却很多(读多)。针对这种场景,Java SDK并发包提供了读写锁——ReadWriteLock,非常容易使用,并且性能很好。二.读写锁允许多个线程同时读共享变量;只允许一个线程写共享变量;如果原创 2020-11-18 01:18:34 · 512 阅读 · 1 评论 -
Java并发Semaphore
文章目录一.信号量二.信号量模型三.使用信号量3.1 示例-累加器3.2 示例-限流器一.信号量Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。二.信号量模型概况为:一个计数器,一个等待队列,三个方法。在信号模型里,计数器和等待队列对外是透明,所以只能通过信号模型提供的三个方法来访问它们,这三个方法分别是:init()、down()、up()。这三个方法详细语原创 2020-11-16 23:37:54 · 525 阅读 · 0 评论 -
Java并发Lock和Condition
文章目录一.简介二.原理2.1 管程2.2 可见性2.3 可重入锁2.4 公平锁与非公平锁2.5 用锁的最佳实践2.6 示例一.简介Java SDK并发包通过Lock和Condition两个接口来实现管程,其中Lock用于解决互斥问题,Condition 用于解决同步问题。二.原理2.1 管程在 Java 的 1.5 版本中,synchronized 性能不如 SDK 里面的 Lock,但 1.6 版本之后,synchronized 做了很多优化,将性能追了上来,所以 1.6 之后的版本又有人推荐原创 2020-11-15 17:20:02 · 571 阅读 · 0 评论 -
死锁
一.简介根据上一篇文章互斥锁死锁实验,死锁定义:一组互相互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。class Account { private int balance; // 转账 void transfer(Account target, int amt){ // 锁定转出账户 synchronized(this){ ① // 锁定转入账户 synchronized(target){ ② if (this.ba原创 2020-11-12 12:35:32 · 1500 阅读 · 5 评论 -
互斥锁
文章目录一.原子问题二.锁模型三.解决方案2.1 synchronized四.保护资源4.1 关系简介4.2 保护没有关联关系的多个资源4.3 保护有关联关系的多个资源4.4 小结一.原子问题在并发编程Bug源头中介绍过,原子问题的源头是线程切换,解决方案禁用线程切换。CPU控制线程切换,无论单核CPU还是多核CPU,保证同一时刻只有一个线程执行,称为互斥,就能够保证对共享变量的修改时互斥,就能保证原子性。二.锁模型互斥的解决方案是锁,把一段需要互斥执行的代码称为临界区。这个锁模型展示的是锁和原创 2020-11-07 19:35:54 · 812 阅读 · 0 评论 -
Java内存模型(解决可见性和有序性问题)
文章目录一.简介二.内存模型三.Happens-Before 规则3.1 规则3.2 final一.简介JMM是一个规范,感兴趣可以查看JSR113标准,描述了JVM平台上多线程程序的语义,具体包括一个线程对共享变量的写入何时能被其他线程“看到”。二.内存模型当指令在CPU上运行的时候,会先将运算需要的数据从内存中复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。(现代CPU其实是有多级缓存的,但原创 2020-10-24 18:04:00 · 2319 阅读 · 3 评论 -
并发编程Bug源头
一.简介编写正确的并发程序是一件困难的事情,往往调试过程中发生很多不确定的事情,这时需要对理论知识的一个认知,能够准确的追踪问题。二.硬件背景CPU,内存,I/O设备不断迭代,这三者速度存在差异,CPU和内存的速度差异可以形象的描述:CPU速度最快,内存次之,I/O设备更次之。为了合理利用CPU的高性能,平衡这三者的速度差异,计算机体系结构、操作系统、编译程序都做出了贡献,主要体现为:CPU增加缓存,以均衡与内存速度差异;操作系统增加了进程、线程,以分时复用CPU,进而均衡CPU与I/O设备的原创 2020-10-12 03:40:36 · 1218 阅读 · 5 评论