concurrent并发包,让你易于编写并发程序。并发下我们经常需要使用的基础设施和解决的问题有ThreadPool、Lock、管道、集合点、线程之间等待和唤醒、线程间数据传输、共享资源访问控制、并发线程之间的相互等待,等待。
concurrent提供的工具能够解决绝大部分的场景,还能提高程序吞吐量。
现代的服务器多采用多核CPU,从而不同线程之间有可能真正地在同时运行而不是cpu时间切片。在处理大计算量的程序上要尽可能利用CPU多核特性,提高系统吞吐量。
并发编程主要面临三个问题:
1.如何让多个线程同时为同一个任务工作(并发编程设计)
2.多个线程之间对共享资源的争用。
3.多个线程之间如何相互合作、传递数据。
1. concurrent包提供的集合
concurrent包直接提供了标准集合的一些实现,在下面做简单介绍。在大部分情况下可以使用它们提供高并发环境下对集合访问的吞吐量。
1.1 ConcurrentHashMap
Map的一个并发实现。在多线程环境下,它具有很高的吞吐量和具备可靠的数据一致性。它支持并发读和一定程度的并发修改(默认16个并发,可以通过构造函数修改)。
HashMap的实现是非线程安全的,高并发下会get方法常会死锁,有的时候会表现为CPU居高不下。
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
在get操作里面for循环取对象的操作,由于高并发同时读写,for循环的结果变得不可预知,所以有可能一直循环。
所以高并发环境下尽量不要直接使用HashMap,对系统造成的影响很难排除。
和Collections.synchronizedMap(new HashMap(...))相比,外ConcurrentHashMap在高并发的环境下有着更优秀的吞吐量。因为ConcurrentHashMap可以支持写并发,基本原理是内部分段,分段的数量决定着并发程度。通过concurrencyLevel参数可以设置。如果你能预期并发数量那么设置该参数可以获取更优吞吐量。
另外为ConcurrentHashMap还实现了:
V putIfAbsent(K key, V value);
boolean remove(Object key, Object value);
boolean replace(K key, V oldValue, V newValue);
V replace(K key, V value);
这四个一致性的操作方法。
1.2 BlockingQueue
BlockingQueue定义了一个接口,继承了Queue接口。Queue是一种数据结构,意思是它的项以先入先出(FIFO)顺序存储。
BlockingQueue为我们提供了一些多线程阻塞语义的方法,新增和重定义了一些方法插入:
BlockingQueue是线程安全的,非常适合多个生产者和多个消费者线程之间传递数据。
形象地理解,BlockingQueue好比有很多格子的传输带系统,不过当你(生产者)调用put方法的时候,如果有空闲的格子那么放入物体后立刻返回,如果没有空闲格子那么一直处于等待状态。add方法意味着如果没有空闲格子系统就会报警,然后如果处理该报警则按照你的意愿。offer方法优先于add方法,它通过返回true 或 flase来告诉你是否放入成功。offer超时方法,如果不空闲的情况下,尝试等待一段时间。
BlockingQueue有很多实现ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue
补充Dueue是个双向队列,可以当做堆栈来使用。
BlockingQueue在ThreadPool中,作为任务队列来使用,用来保存没有立刻执行的工作任务对象。
1.3 SynchronousQueue
SychronousQueue是BlockingQueue的一个实现,它看起来是一个队列,但是其实没有容量,是特定条件下的一个精简实现。
做个比喻,SychronousQueue对象就像一个接力棒,现在有两个运动员交棒者和接棒者(线程)要做交接。在交接点,交棒者没有交出之前是不能松开的(一种等待状态),接棒者在接到棒之前是必须等待。换一句话说不管谁先到交接点,必须处于等待状态。
在生产者和消费者模型中。如果生产者向SychronousQueue进行put操作,直到有另外的消费者线程进行take操作时才能返回。对消费者也是一样,take操作会被阻塞,直到生产者put。
在这种生产者-消费者模型下,生产者和消费者是进行手对手传递产品,在消费者消费一个产品之前,生产者必须处于等待状态。它给我们提供了在线程之间交换单一元素的极轻量级方法,并且具有阻塞语义。
提示:上面举例中有写局限性。其实生产者和消费者进程是可以任意数量的。M:N。生产线程之间会对SychronousQueue进行争用,消费者也是一样。
对SychronousQueue类似于其他语境中“会合通道”或 “连接”点问题。它非常适合于传递性设计,在这种设计中,在一个线程中运行的对象要将某些信息、事件或任务传递给在另一个线程中运行的对象,它就必须与该对象同步。
1.4Exchanger
是SychronousQueue的双向实现。用来伙伴线程间交互对象。Exchanger 可能在比如遗传算法和管道设计中很有用。
形象地说,就是两个人在预定的地方交互物品,任何一方没到之前都处于等待状态。
1.5 CopyOnWriteArrayList 和 CopyOnWriteArraySet
它们分别是List接口和Set接口的实现。正如类名所描述的那样,当数据结构发生变化的时候,会复制自身的内容,来保证一致性。大家都知道复制全部副本是非常昂贵的操作,看来这是一个非常不好的实现。事实上没有最好和最差的方案,只有最合适的方案。一般情况下,处理多线程同步问题,我们倾向使用同步的 ArrayList,但同步也有其成本。
那么在什么情况下使用CopyOnWriteArrayList 或者CopyOnWriteArraySet呢?
- 数据量小。
- 对数据结构的修改是偶然发生的,相对于读操作。
举例来说,如果我们实现观察者模式的话,作为监听器集合是非常合适的。
1.6 TimeUnit
虽然是个时间单位,但是它也是concurrent包里面的。也许你以前的代码里面经常出现1*60*1000来表示一分钟,代码可读性很差。现在你可以通过TimeUnit来编写可读性更好的代码,concurrent的api里面涉及到时间的地方都会使用该对象。
我之所以先进并发框架常用的集合,是因为线程池的实现特性都利用了BlockingQueue的一些特性。
相关推荐
本书《Concurrent Programming in Java》第二版是关于Java并发编程的权威经典作品,由Doug Lea撰写。在本书中,作者提供了关于Java 2平台的全面更新覆盖,以及对内存模型、取消机制、可移植的并行编程和并发控制的...
《Java并发编程:设计原则与模式》是一本深入探讨Java多线程编程的权威书籍,由Doug Lea撰写,第二版全面涵盖了Java并发处理的各个方面。这本书不仅提供了丰富的理论知识,还介绍了实战中的设计原则和模式,对于Java...
最后,"Addison_Wesley_-_Concurrent_Programming_in_Java_2nd_Ed_(1999).pdf"是《并发编程在Java》的第二版,由Doug Lea撰写。这本书是Java并发编程领域的另一部里程碑作品,它在Java 1.4时代就深入介绍了线程、...
18 适用于 Java 程序员的 CSP,第 1 部分.mht 19 适用于 Java 程序员的 CSP ,第 2 部分.mht 20 适用于 Java 程序员的 CSP ,第 3 部分.mht 21 实现一个不受约束的不变性模型.mht 22 实时 Java,第 3 部分 线程...
《Thinking in Java》是Bruce Eckel的经典编程教材,第四版更是深受广大Java程序员喜爱。这本书深入浅出地讲解了Java语言的核心概念和技术,是学习Java的宝贵资源。源代码是理解书中理论的最佳实践,通过阅读和运行...
6. **多线程**:Java提供了强大的多线程支持,书中会讲解线程的创建、同步、互斥等概念,以及synchronized关键字和java.util.concurrent包中的高级工具。 7. **泛型**:泛型是Java 5引入的新特性,用于提高代码的...
Java JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的软件工具包,而JDK6是Java的一个重要版本,发布于2006年。本篇将详细介绍Java JDK6的安装过程及其相关知识点。 一、Java JDK6概述...
《Think in Java》是 Bruce Eckel 编著的一本经典Java编程教材,其第四版深受全球程序员喜爱。这本书深入浅出地介绍了Java语言的核心概念和技术,包括面向对象编程、泛型、集合框架、多线程、网络编程等。提供的...
第四版则是针对Java SE 5.0及以后的版本,引入了更多的新特性,如注解(Annotations)、并发工具包(Concurrent Package)的增强、nio(New I/O)等。在这一版中,你将学到: 1. **注解**:了解如何使用注解来提供...
6. **其他有用类**:`java.util.concurrent`包提供了线程安全的集合和并发工具,如`ExecutorService`,`Semaphore`等,有助于多线程编程。`java.util.Random`用于生成随机数,`java.util.UUID`则生成全局唯一的...
本书《Learning Concurrent Programming in Scala》旨在深入讲解如何利用Scala进行高效并发编程。 #### 二、传统并发与现代并发范式 - **传统并发**:主要包括多进程和多线程模型。在传统并发模型中,每个进程或...
15. **Java API**:熟悉Java提供的各种API,如集合框架、I/O流、日期时间API(java.time包)、并发包(java.util.concurrent)等,将大大提高开发效率。 以上只是Java基础部分的一部分知识点,完整的自学过程可能还...
《Thinking in Java》是Java编程领域的一本经典著作,由Bruce Eckel撰写,深受程序员喜爱。这本书深入浅出地介绍了Java语言的核心概念和技术,旨在帮助读者建立起扎实的面向对象编程思维。英文版提供了原汁原味的...
第一部分重点讲解了Java并发的基础知识和技术,包括线程安全、对象共享以及对象组合等。 - **第2章:线程安全** 本章首先定义了什么是线程安全,并通过原子性和锁定机制来实现这一目标。接着介绍了如何利用锁保护...
这里提到的"Java API(分两次传,第一部分)"可能是指Java 1.6版本的API文档或库,这是一个重要的里程碑,因为它在Java的发展历程中占有显著位置。 Java API 主要分为几个部分: 1. **核心类库**:这是Java API的...
1. **第一章:并发的基本概念** - 引导读者理解并发编程的基本原理,包括线程、进程、执行模型以及并发带来的挑战。 2. **第二章:避免并发问题** - 介绍如何通过使用不可变对象、最小化共享状态和正确使用同步来...
Java集合框架是Java编程语言中的核心部分,它为组织和管理对象提供了强大的工具。在Java SE的第07章中,我们通常会深入探讨这个关键主题。本课件旨在为初学者提供一个全面且深入的理解,帮助他们掌握Java集合框架的...
在中文版的《Think in Java第四版》中,读者可以全面了解Java编程的基础知识,包括但不限于: 1. **基础语法**:学习Java的基本数据类型、变量、常量、运算符以及流程控制语句,如if-else、switch、for、while等,...
java.util.concurrent.locks 为锁和等待条件提供一个框架的接口和类,它不同于内置同步和监视器。 java.util.jar 提供读写 JAR (Java ARchive) 文件格式的类,该格式基于具有可选清单文件的标准 ZIP 文件格式。 ...
6. **多线程**:Java提供了丰富的多线程支持,包括Thread类、Runnable接口和并发包(java.util.concurrent)。多线程编程涉及同步、互斥、线程池等概念,是高并发场景下的必备知识。 7. **输入/输出流**:Java的I/O...