A collection of 49 posts

LockSupport源码分析

concurrent包基于AQS框架,AQS框架基于两个类: Unsafe(提供CAS操作) LockSupport(提供park/unpark操作) 概念 LockSupport public static void park() { UNSAFE.park(false, 0L); } public static void ...

并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别? - 《Java 核心技术》笔记

Concurrent* 容器,基于lock-free,在常见的多线程访问场景,一般可以提供较高吞吐量; LinkedBlockingQueue内部基于锁,并提供了BlockingQueue的等待性方法。 Concurrent* 性质 java.util.concurrent包提供的容器(Queue、List、Set)、Map从命名上可以大概分为Concurrent* 、CopyOnWrite和Blocking等三类: Concurrent没有类似CopyOnWrite之类容器相对较重的修改开销; Concurrent提供了较低的遍历一致性。比如当利用迭代器遍历时, ...

Java并发包提供的并发工具类 - 《java核心》笔记

提供了各种丰富的同步结构,包括CountDownLatch、CyclicBarrier、Semaphore等,可以实现更加丰富的多线程操作,比如利用Semaphore作为资源控制器,限制同时进行工作的线程数量; 各种线程安全的容器,比如ConcurrentHashMap,有序的ConcurrentSkipListMap,通过类似快照机制实现线程安全的动态数组CopyOnWriteArrayList; 各种并发队列实现,比如BlockedQueue,ArrayBlockingQueue、SynchorousQueue,或针对特定场景的PriorityBlockingQueue等; 强大的Executor,可以创建各种不同类型的线程池,调度任务运行等。 问题 ...

死锁 - 《Java 核心》笔记

定位死锁常见方式 必定会出现死锁的程序: public class DeadLockSample extends Thread { private String first; private String second; public DeadLockSample(String name, String first, String ...

ConcurrentSkipListMap实现原理

跳表介绍 跳表是一种随机层次的数据结构,通过建立多级索引,实现以二分查找遍历一个有序链表。 SkipList让已排序的数据分布在多层链表中,以0~1随机数决定一个数据的向上攀升与否,以时间换空间的一个算法。 SkipList的性质: 多层结构,level通过一定概率随机产生; 每一层都是一个有序链表; 最底层包含所有元素; 如果一个元素出现在第i层,则i层以下也包含这个元素; 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。 性能对比 ConcurrentHashMap和ConcurrentSkipListMap对比, ...

Phaser

Phaser是JDK1.7引入的一个同步工具类,适用于一些需要分阶段的任务处理。一种人物可以分为多个阶段,现希望保证只有前面一个阶段的任务完成后才能开始后面的任务。这种场景可以使用多个CyclicBarrier来实现,但是需要明确知道总共有多少个阶段,且无法动态修改。Phaser可以同时解决这两个问题。 同步器 作用 CountDownLatch 倒数计时器 CyclicBarrier 循环栅栏,初始时设定参与线程数,当线程到达栅栏后,会等待其他线程的到达。当到达栅栏的总数满足指定数后,所有等待的线程继续执行。 ...

ForkJoinPool

ForkJoinPool的作用 ThreadPoolExecutor每个任务都是单独线程处理的。如果某个任务耗时很大,就可能出现其他线程都在等着这个线程结束的情况。 为了处理这种问题,ForkJoinPool将一个大任务拆分为多个小任务,使用fork可以将小任务分发给其他线程同时处理,使用join可以将多个线程处理的结果进行汇总。 ForkJoinPool的原理 ForkJoinPool中每个线程都有自己的双端列表用于存储任务。这个双端列表对于工作窃取算法非常重要。 public class ForkJoinWorkerThread extends Thread { final ForkJoinPool pool; // 工作线程所在的线程池 ...

协程

why 协程 协程的两大特点: 占用的资源更少; 所有的切换和调度都发生在用户态。 协程是一种轻量级、用户态的执行单元。拥有自己的寄存器上下文和栈。协程调度切换时,把寄存器上下文和栈保存到其他地方。在切回来的时候再恢复回来。 线程:抢占式多任务。 协程:协作式多任务。 不管是进程还是线程,阻塞、切换调度的时候都需要陷入系统调用,由CPU跑调度程序,再由调度程序决定跑哪一个进程( ...

Java Instrument

作用 Java Instrument指的是可以用独立于应用程序之外的代理程序来监测和协助运行在JVM上的应用程序,包括但不限于获取JVM运行时状态,替换和修改类定义。 使用方法 Java SE5及以后的版本,可以在一个普通Java程序运行时,通过-javaagent参数制定一个特定的jar文件(包含Instrumentation代理)来启动Instrumentation的代理程序。 代理类必须提供一个public static void premain(String args, Instrumentation inst) ...

java多线程(5) - Java虚拟机中的锁优化技术以及几种锁的介绍

线程的五种状态: 自旋锁 在程序中,Java虚拟机的开发工程师们在分析过大量数据后发现,共享数据的锁定状态一般只会持续很短的一段时间,为了这段时间去挂起和恢复线程其实并不值得。 如果物理机上有多个处理器,可以让多个线程同时执行的话,就可以让后来的线程“稍微(忙)等一下”,不会放弃处理器事件,看看持有锁的线程会不会很快释放锁。这个“稍微等一下”的过程就是自旋。 锁消除 在动态编译同步块的时候,JIT编译器可以借助一种叫逃逸分析( ...

java多线程(4) - Moniter的实现原理

Moniter是什么 我们可以把监视器理解为包含一个特殊的房间的建筑物,这个特殊房间同一时刻只能有一个客人。如果一个顾客想要进去这个房间,就需要在走廊(Entry Set)排队,调度器将基于某个标准来选择排队的客户进入房间。如果用户暂时因为其他事情无法脱身,那么就会被送到等待室(Wait Set)。 监视器是一个用来监视这些线程进入特殊的房间的,它的义务是保证(同一时刻)只有一个线程可以访问被保护的数据和代码。 Monitor其实是一种同步机制,通常被描述为一个对象,其主要特点是: ...

java多线程(2) - Java的对象模型

java对象保存在堆内存中。在内存中,一个Java对象包含三部分:对象头、实例数据和对象填充。 对象头中包含锁状态标志、线程持有的锁等标志。 Java的对象模型 在JVM的内存结构中,对象保存在堆内存中。我们在对对象进行操作时,操作的是对象的引用。 那么对象本身在JVM中的结构是什么样的? oop-klass model HotSpot JVM的设计者不想让每个对象中都含有一个vtable(虚函数表)(HotSpot基于C++实现) ...

谈谈接口和抽象类有什么区别? - 《java核心技术》笔记

回答 接口是行为的抽象,是抽象方法的集合,目的是API定义和实现分离。不包含任何非常量成员以及非静态方法;java8后增加了default method,java9后可以定义private defult method。比如java8中的Collection增加了一系列关于Lambda、Stream的default method。 抽象类是不能被实例化的类,主要目的是代码重用。 S.O.L.I.D原则 ...

Java有几种文件拷贝方式?哪一种最高效? - 《java核心技术》笔记

java的几种文件拷贝方式?哪一种最高效? java.io的FileInputStream/FileOutputStream或者java.nio的transferTo/transferFrom。 nio方式可能更快,因为使用了零拷贝技术,数据传输不需要切换到用户态参与,减少了上下文切换和不必要的内存拷贝。 比如应用读取数据时,先在内核态将数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存。 而NIO transferTo则直接在内核中进行数据拷贝。 提高类似拷贝等IO操作的性能的原则 使用缓存,减少IO次数; 使用transferTo等机制, ...

Java提供了哪些IO方式? NIO如何实现多路复用? - 《java核心技术》笔记

简述 同步阻塞IO库:传统的java.io包下面一些熟知的IO功能,比如File抽象,输入输出流等,交互方式是同步阻塞。java.net下面提供的部分网络API,比如Socket、ServerSocket、HttpURLConnection; 1.4引入的NIO,提供了Channel、Selector、Buffer等新的抽象,可以用于构建多路复用的、同步非阻塞IO,同时提供了更接近OS底层的高性能数据操作方式; ...

如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全? - 《java核心技术》笔记

简述 问:为什么需要ConcurrentHashMap? 答:因为Hashtable本身比较低效,它在所有的put、get、size方法上面加上了“synchronized”。而Collections提供的同步包装器,只是将“this”作为互斥的mutex。 早期的ConcurrentHashMap基于: 分段锁,将内部进行分段(Segment),里面是HashEntry的数组; HashEntry内部使用volatile的value字段保证可见性,也利用了不可变对象的机制以改进利用Unsafe提供的底层能力, ...

Exception和Error的区别-《Java核心技术》笔记

Exception是程序正常运行时可以预料到并且应该被捕获的情况,Error是指在正常情况下不太可能出现的情况。绝大部分Error都会导致程序处于非正常、不可恢复的情况,所以不便于也不应该被捕获,比如OutofMemoryError。Exception分为checked和unchecked,checked在代码里必须显式捕获,比如IOException,而unchecked是不可查异常,比如NullPointerException、ArrayIndexOutOfBoundException,通常是可以编码避免的逻辑错误。 抛异常的最佳实践:throw early,catch late。 try-catch会产生额外的性能开销,建议仅捕获有必要的代码段, ...

“解释执行”的理解-《Java核心技术》笔记

编译是将源程序翻译成可执行的目标代码,翻译与执行是分开的。而解释是对源程序的翻译与执行一步到位完成,不生成可存储的目标代码。最大的区别在于控制权:对于解释执行而言,程序运行时的控制权在解释器而不在用户程序;对编译执行而言,程序运行时的控制权在用户。 根据程序执行时的基本表示是实际计算机上的机器语言还是虚拟机的机器语言,可以分为两大类:编译型语言和解释型语言。 由编译型语言编写的源程序需要经过编译、汇编和链接才能生成目标代码,然后机器执行目标代码得出结果。目标代码由机器指令组成,一般不能独立运行; 解释型语言中,翻译器并不生成目标代码,而是产生易于执行的中间代码, ...

java一些优化点

减少临时对象; 减少list的拷贝,如果要添加到末尾,不要新增一个临时对象; 在初始化map和list的时候,在一开始设置初始化容量,减少扩容引起的数据拷贝; if else如果是string,用switch替换; 删除缓存可能会引起性能提升; 可以按照index寻址的,不要用map。 其实思路跟C++差不多。 ...