Java并发编程那些事儿(十)——最后的总结

这是并发编程系列的第十篇文章,也是最后一篇文章。这篇文章将会对之前的文章内容做一个简单的总结和梳理。

要学习并发编程,首先要了解什么是线程,什么是任务,以及线程和任务之间的关系,这部分内容在第一篇文章有提到。

并发编程要解决的核心问题就是如何做到多个线程安全的读写共享变量。想做到安全的读写共享变量一共有两个方法。第一个方法是通过加锁的方式实现。第二个方法就是避免竞争,每个线程都持有一份共享变量的拷贝,也就是大家常用的ThreadLocal。这两种方法,分别在第二篇第三篇有详细的介绍。

并发编程除了要解决多线程安全读写共享变量的问题,还要解决线程间互相通信的问题。因为有些任务,线程间必须互相配合才能更快速的完成任务,比如一个线程负责洗碗,一个线程负责烘干,那么烘干任务必须在洗碗线程结束之后才能开始。Java里面有两种实现线程间通信的方法,分别是基于内置锁的wait()notify()方法,以及基于显示锁的await()signal()方法。这部分内容的详细介绍可以看我的第四篇文章。

上面所有的内容都是如何保证同一时刻只有一个线程在工作,实际工作中我们往往希望,某一个时刻有固定数量的线程在工作,比如用户并发量,这个时候我们可以通过使用Semaphore来实现。这是Java提供的内置工具类,类似的工具类还有CountdownLatch等。具体的介绍可以看第五篇文章。

线程的创建和销毁是一件很耗费系统资源的事情,而且线程不能无限创建,因为每个线程都会占用大概1M的内存空间,为了保证我们更快的使用资源,实际项目中,都会采用线程池的方式使用线程。Java提供了Executor框架让我们方便的使用线程池,同时Executor还成功的将线程和任务进行了解耦。总之实际编程过程中都会使用Executor框架。具体如何使用可以参考第六篇文章。

知道如何创建并启动线程很重要,但是知道如何安全的终止线程更加重要。就好比如何让飞机安全平稳的落地比知道飞机如何起飞更重要一样。第七篇文章详细介绍了线程终止的内容。

死锁,并发编程最希望避免的问题,但是你好像总是踩在坑里。第八篇文章介绍了死锁相关问题。希望能帮你避坑。

并发编程的所有问题,归根结底都会回归本质,那就是JVM内存模型。所以了解JVM,了解JVM内存模型才是关键。在第九篇文章中介绍了内存相关的知识。

最后附上所有文章的链接:

Java并发编程那些事儿(一) ——任务与线程
Java并发编程那些事儿(二)——锁
Java并发编程那些事儿(三)——ThreadLocal及原子性与可见性
Java并发编程那些事儿(四)——线程间的协作
Java并发编程那些事儿(五)——闭锁、栅栏、信号量
Java并发编程那些事儿(六)——Executor框架及线程池
Java并发编程那些事儿(七)——取消及关闭
Java并发编程那些事儿(八)——死锁
Java并发编程那些事儿(九)——内存模型


推荐阅读
1. Java并发编程那些事儿(一) ——任务与线程
2. Java8的Stream流真香,没体验过的永远不知道
3. Awk这件上古神兵你会用了吗
4. 手把手教你搭建一套ELK日志搜索运维平台

-------------本文结束-------------
坚持原创技术分享,您的支持将鼓励我继续创作!
0%