摘要:1.线程池参数 2.线程池执行流程 2.1 流程图 2.2 线程创建的流程 当任务提交之后,线程池首先会检查当前线程数,如果当前的线程数小于核心线程数(corePoolSize),比如最开始创建的时候线程数为 0,则新建线程并执行任务。当提交的任务不断增加,创建的线程数等于核心线程数(corePoo
阅读全文
摘要:1.拒绝时机 线程池会在以下两种情况下会拒绝新提交的任务 当我们调用 shutdown 等方法关闭线程池的时候,如果此时继续向线程池提交任务,就会被拒绝当任务队列(workQueue)已满,而且线程达到最大线程数(maximumPoolSize),如果再增加任务,也会被拒绝 2.拒绝策略 2.1 核
阅读全文
摘要:答案:不能 线程之间的关系,是“协同式”的,不是“抢占式”的。 yield不会强制让渡CPU, interrupt也不会强制停止线程。 根据源码注释: 调用yield,只是想处理器processor暗示:“当前线程愿意让渡yield时间片”。但是处理器可以自由的忽略这个暗示。 这就说明了:线程之间的
阅读全文
摘要:总结 JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happens-before关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证a操作将对b操作可见) happens-before定义 happens-
阅读全文
摘要:一、线程池对应的阻塞队列 LinkedBlockingQueue 第一种阻塞队列是 LinkedBlockingQueue,它的容量是 Integer.MAX_VALUE,为 231 -1 ,是一个非常大的值,可以认为是无界队列。 FixedThreadPool 和 SingleThreadExec
阅读全文
摘要:一、总结 有两种: 通过Executors工厂方法创建 通过new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable>
阅读全文
摘要:频繁创建新线程有什么缺点? 1.不受控风险 系统资源有限,每个人针对不同业务都可以手动创建线程,并且创建标准不一样(比如线程没有名字)。当系统运行起来,所有线程都在疯狂抢占资源,无组织无纪律,内存很容易被无情榨干耗尽。 另外,过多的线程自然也会引起上下文切换的开销。 2.频繁创建开销大 new Th
阅读全文
摘要:如何让ThreadPoolExecutor更早地创建非核心线程
阅读全文
摘要:总结 1. 什么是AQS ? AQS的全称是AbstractQueuedSynchronizer,它是为Java中几乎所有的锁和同步器提供一个基础框架, 拥有一个同步队列和多个等待队列: 1.1 AQS vs 锁 锁和同步器很好地隔离了使用者和实现者 所需关注的领域: 锁是面向使用者的,它定义了使用
阅读全文
摘要:1-Jconsole 检查死锁 Jconsole是JDK自带的图形化界面工具,使用JDK给我们的的工具JConsole,可以通过打开cmd然后输入jconsole打开。 连接到需要查看的进程。 打开线程选项卡,然后点击左下角的“检测死锁” 。 jconsole就会给我们检测出该线程中造成死锁的线程,
阅读全文
摘要:synchronized 和 volatile 的区别是什么? 作用: synchronized 表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程。volatile 表示变量在 CPU 的寄存器中是不确定的,必须从主存中读取。保证多线程环境下变量的可见性;禁止指令重排序。 区别: syn
阅读全文
摘要:Exchange Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger 用于进行 线程间的数据交换。它供一个同步点,在这个同步点,两个线程可以交换彼此 的数据。这两个线程通过 exchange 方法交换数据。 如果第一个线程先执行 exchange()方法,它会一直等待第
阅读全文
摘要:总结 1-Semaphore 的构造方法 Semaphore(int permits)接受一个整型的数字, 表示可用的许可证数量 2-线程使用 Semaphore 的 acquire()方法获取一个许可证,使用完之后调用 release()方法归还许可证。还可以用 tryAcquire()方法尝试获
阅读全文
摘要:CountDownLatch VS CyclicBarrier CountDownLatch 的计数器只能使用一次,而 CyclicBarrier 的计数器可以反复使用 在控制多个线程同时运行上,CountDownLatch 可以不限线程数量,而 CyclicBarrier 是固定线程数。 Cycl
阅读全文
摘要:Fork-Join原理 任务fork,结果join 工作密取 即当前线程的 Task 已经全被执行完毕,则自动取到其他线程的 Task 池中取 出 Task 继续执行。 ForkJoinPool 中维护着多个线程(一般为 CPU 核数)在不断地执行 Task,每 个线程除了执行自己职务内的 Task
阅读全文
摘要:总结 AtomicLong AtomicLong 是基于 CAS 方式自旋更新的。 唯一会制约AtomicLong高效的原因是高并发,高并发意味着CAS的失败几率更高, 重试次数更多,越多线程重试,CAS失败几率又越高,变成恶性循环,AtomicLong效率降低。 LongAdder LongAdd
阅读全文
摘要:什么是原子操作?如何实现原子操作? 假定有两个操作 A 和 B,如果从执行 A 的线程来看,当另一个线程执行 B 时, 要么将 B 全部执行完,要么完全不执行 B,那么 A 和 B 对彼此来说是原子的。 实现原子操作可以使用锁,锁机制,满足基本的需求是没有问题的了,但是 有的时候我们的需求并非这么简
阅读全文
摘要:Lock 接口 Lock 标准用法 在 finally 块中释放锁,目的是保证在获取到锁之后,最终能够被释放。 不要将获取锁的过程写在 try 块中,因为如果在获取锁(自定义锁的实现) 时发生了异常,异常抛出的同时,也会导致锁无故释放。 Lock 常用 API public interface Lo
阅读全文
摘要:总结 先抛出我的结论:用CAS方式获取锁的,并非都是乐观锁。 我们在Java里使用的各种锁,几乎全都是悲观锁。synchronized从偏向锁、轻量级锁到重量级锁,全是悲观锁。JDK提供的Lock实现类全是悲观锁。其实只要有“锁对象”出现,那么就一定是悲观锁。因为乐观锁不是锁,而是一个在循环里尝试C
阅读全文
摘要:总结 1-悲观锁:Java里使用的各种锁:互斥锁、自旋锁、读写锁,都是属于悲观锁。悲观锁做事比较悲观,它认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁。 2-乐观锁:Java里很少有乐观锁。目前据我所知,java.util.concurrent.atomic
阅读全文