Java

HashMap的源码分析

HashMap基于散列表,散列表中每一个Node节点(桶)是链表,当两个条目(entry)的key的hash值对桶数(capacity)取模的值相等时,这两个entry会存储在同一个链表中。但当链表中元素达到一定数目时,链表结构会转变为树结构

本文从初始化,扩容,插入,获取,删除这几个方面深入讨论了HashMap的实现细节。

此文中没有讨论HashMap中涉及到树结构的源码。

...

线程本地存储

使用synchronized关键字对整个方法加锁(防止其他线程访问整个方法)往往会带来更大的性能开销,如果你只想保护某些代码块,可以使用同步代码块,这一段被锁保护的代码块就称为临界区critical section ),前面的显式锁所保护的区域以及使用synchronized保护的代码块都是临界区。

...

Lambda与函数式接口

Java 函数式接口和Lambda表达式是 Java 8 中引入的一个重要概念,它允许你将行为作为参数传递给方法,从而实现更简洁、更灵活的代码。

Lambda表达式 #

Lambda表达式是一个可传递的代码块,可以在以后执行一次或多次

...

获取任务的返回值

获取任务的返回值 #

要创建一个任务,通常实现Runnable接口。不幸的是,Runnable接口的run()方法返回void,因此,其并不适合处理计算任务。

考虑一个经典的问题:用多线程分段计算0-100的加和,我们需要把每个线程计算的值汇总,然后再求和,那么应该怎样获取每个任务返回值呢?

Java提供了CallableFuture接口,使任务有提供返回值的能力。

...

Collections工具类

集合框架中一个重要的类,其实是Collection接口的伴随类,其中定义了许多实用方法,用来获取集合视图,或提供一些方便的操作集合元素的算法

由于视图是直接封装的Collection接口,因此其方法有些局限,并且由于特殊的设计,部分操作是不允许的(会抛出 UnsupportedOperationExceptin )。

...

内部类

将一个类定义在另一个类的内部,这就是内部类。

定义言简意赅 ,内涵丰富多彩。

...

死锁问题2例

Java有能力使任务为等待某些条件成立而进入阻塞状态,所以就有可能出现这样一种情况:某个任务在等待另一个任务,而后者又在等待其他的任务,这样一直等待下去,直到等待链上的最后一个任务又在等待第一个任务释放锁,这样就出现了任务之间相互等待的连续循环现象,这种情况出现之后,没有哪个任务能够执行,于是 死锁 出现。

死锁之所以难以规避,其重要的原因就在于其不确定性,可能程序运行良好,但是有潜在的死锁风险,这个风险在某些域的初始条件变化时,变得特别大,导致程序很快死锁。同时,死锁难以复现,当程序出现死锁时,往往只能通过jvm的堆栈日志来探究原因。

...

终结任务

终结任务 #

一般地,如果程序运行良好,任务执行完所需操作后自然结束,任务终结。

如果任务执行时出现异常,任务也会终结。

在设计多个线程协同工作的任务时,需要判断任务终结的条件,以便合适地终结任务,这点尤为重要。

在本节中主要讨论在多线程协同工作的情况下,如何合适的终结任务。

...

生产者-消费者与阻塞队列

在讨论线程协作的时候,已经讨论了生产者与消费者雏形,比如录音是生产者,而播放则是消费者;同样的,在汽车打蜡的模型中,打蜡可看作生产者,抛光可看作消费者;只是它们的关系是简单的生产-消费关系。

除了简单的线程协同之外,Java提供了同步队列来解决线程的协同问题,本节重点讨论这部分的内容。

...