线程

线程

提示

有了进程为什么还要有线程?线程越多执行就越快吗?

尽管在平时的开发中,我们很少会直接编写多线程代码,但是,常用的框架和容器,无一例外的都会用到多线程。比如,Dubbo、Tomcat均使用多线程来处理请求。业务代码一般运行在这些框架或容器中,因此,也就间接的会用到多线程。只有对多线程的使用和原理有透彻的了解,我们才能编写出线程安全且高性能的代码。

在正式的学习如何编写多线程代码之前,我们先介绍多线程方面的一些基础理论知识,其中包括:线程的由来、调度策略、线程状态、线程模型、Java线程的实现方式。


Mr.ZhangJava多线程大约 25 分钟
ConcurrentHashMap

ConcurrentHashMap

提示

分段加锁:HashMap线程不安全的原因及ConcurrentHashMap的实现

HashMap是在开发中经常用到的容器,但是,它不是线程安全的,只能应用于单线程环境下。在多线程环境下,Java提供了线程安全的HashTable、SynchronizedMap,但是,两者因为采用粗粒度锁来实现,并发性能不佳。于是,JUC便开发了ConcurrentHashMap,利用分段加锁等技术来提高并发性能。本节,我们就来详细讲解一下ConcurrentHashMap的实现原理,这也是面试中经常被问到的地方。

这里特别声明一下,HashMap和ConcurrentHashMap在JDK7和JDK8中的实现方式均有较大差别,在本节中,我们参照JDK8中的实现方式来讲解。


Mr.ZhangJava多线程大约 18 分钟
写时复制

写时复制

提示

为什么JUC只支持数组类型的写时复制并发容器?

上一节,我们对JUC并发容器做了一个框架性介绍,提到了很多并发容器。本节,我们讲解其中的CopyOnWriteArrayList和CopyOnWriteArraySet,它们都是采用写时复制技术来实现,因此,称为写时复制并发容器。从名称,我们可以发现,这两个容器都跟数组有关。那么,为什么JUC没有提供CopyOnWriteLinkedList、CopyOnWriteHashMap等其他类型的写时复制并发容器呢?带着这个问题,我们来学习本节的内容。


Mr.ZhangJava多线程大约 11 分钟
阻塞等待

阻塞等待

提示

如何实现支持阻塞读写的线程安全队列(阻塞并发队列)?

在讲解条件变量和信号量时,我们留给大家思考如何使用条件变量或信号量来实现阻塞并发队列。本节我们就结合JUC源码来看下工业级的阻塞并发队列,到底是怎么实现的,都有哪些值得我们学习的地方。

一、阻塞并发队列

阻塞并发队列具有两个特点,第一个是线程安全,也就是名称中“并发”的含义,第二个是支持读写阻塞,也就是名称中“阻塞”的含义。读阻塞指的是,当从队列中读取数据时,如果队列已空,那么读操作阻塞,直到队列有新数据写入,读操作才成功返回。写阻塞指的是,当往队列中写入数据时,如果队列已满,那么写操作阻塞,直到队列重新腾出空位置,写入操作才成功返回。阻塞并发队列一般用于实现生产者-消费者模型。


Mr.ZhangJava多线程大约 12 分钟
并发容器

并发容器

提示

如何实现线程安全的数组、链表、哈希表等常用数据结构?

为了方便开发,Java提供了很多容器,比如ArrayList、HashMap、TreeSet等,底层对数组、哈希表、红黑树等常用的数据结构进行了封装。在开发时,我们直接使用这些现成的容器即可,不需要重新从零去开发。对于这些封装了常用数据结构的容器,在多线程环境下,我们如何来保证它们的线程安全性呢?

依靠程序员自己去编写代码,比如对操作加锁,来维护容器的线程安全性,一来耗费开发时间,二来性能没有保证。为了解决这个问题,JUC针对常用的容器,对应开发了高性能的并发容器。在多线程编程中,我们直接使用这些现成的并发容器即可。

从本节开始,我们就来详细讲解一下,JUC并发容器的用法和实现原理。在正式开始之前,本节先对JUC并发容器做一个框架性的介绍,让你对JUC并发容器有一个系统性的认识。


Mr.ZhangJava多线程大约 5 分钟
锁存器和栅栏

锁存器和栅栏

提示

如何编程测试接口在不同并发下的性能?

在平时开发中,有时候,我们需要自己编写代码,测试某个接口在不同并发下的性能,比如测试在N个(N可以是100、200等任意数)接口请求并发执行时接口的响应时间、QPS等。为了模拟接口的并发请求,我们需要用到多线程。除此之外,线程之间的协调执行,还需要用到本节要讲的CountDownLatch和CyclicBarrier。接下来,我们就结合这个需求的开发,详细讲解一下CountDownLatch和CyclicBarrier的用法以及实现原理。


Mr.ZhangJava多线程同步工具类大约 9 分钟
信号量

信号量

提示

如何使用信号量来限制并发执行某个接口的线程数?

信号量是并发编程中的一个重要概念,JUC提供了Semaphore类来实现信号量。信号量用来限制临界区和共享资源的并发访问。使用互斥锁,临界区和共享资源同时只能被一个线程访问;使用信号量,临界区和共享资源同时可以被多个线程访问。因此,信号量也可以看做是一种共享锁,其底层也是基于AQS实现的。


Mr.ZhangJava多线程同步工具类大约 10 分钟
条件变量

条件变量

提示

为什么使用条件变量之前要先加锁?

互斥和同步是多线程要解决的两个核心问题,互斥依靠互斥锁来解决,其中包含synchronized、Lock、CAS、原子类、累加器等。同步依靠同步工具来解决,其中包括条件变量、信号量、CountDownLatch、CyclicBarrier等。在前面几节,我们已经对互斥锁做了详细讲解,在接下来的几节,我们详细讲解同步工具。


Mr.ZhangJava多线程同步工具类大约 16 分钟
线程执行框架

线程执行框架

提示

如何获取一个线程所执行的代码的运行结果?

本节,我们来讲线程执行框架。线程执行框架提供了一系列类,封装了线程创建、关闭、执行、管理等跟业务逻辑无关的代码逻辑,这样做一方面实现了业务逻辑与非业务逻辑的解耦,另一方面方便代码复用,开发者不再需要编写创建线程、启动线程等代码。实际上,上一节中讲到的ThreadPoolExecutor、Executors就隶属于线程执行框架。在开始本节的正式内容之前,我还是给你出一道思考题:如何获取一个线程所执行的代码的运行结果?


Mr.ZhangJava多线程大约 5 分钟
线程中断

线程中断

提示

如何安全地提前终止正在执行业务逻辑的线程?

大部分情况下,线程在执行完业务逻辑之后便自行结束,但是,少数情况下,由于应用程序关闭等原因,线程在执行业务逻辑的过程中有可能提前被终止。我们需要寻找一些安全的线程终止方式,避免突然中止业务逻辑而导致的数据不一致、资源得不到回收等问题。本节,我们就详细讲一讲,如何安全地提前终止线程,并且重点讲解其中的中断方法。


Mr.ZhangJava多线程大约 9 分钟
2