首先了解同步容器,同步容器将所有的容器状态的访问都实现串行化,以保证线程安全性,比如:HashMap,List,Map,List等等,这种方法代价严重降低并发性,当多个线程竞争容器锁时,吞吐量会严重降低,JAVA5就提供了多种并发容器来改进同步容器的性能。例如:ComcurrentHashMap,CopyOnWriteArrayList
,ConcurrentMap,ConcurrentLinkedQueue。BlockingQueue等,介绍三种。
1.ConcurrentHashMap
同步容器类在执行每个操作的期间都持有一个锁,在以下操作中HashMap.get后Lint.contains,可能包括大量工作:当遍历散列桶或链表来查找某个元素时,如果hash不是均匀分布,可能要多次调用equal方法,而对链表调用contains方法时,要遍历整个链表,这样会花费很长的时间,在这段时间内其他线程是不能访问这个容器的,这样极大影响了并发性。而ConcurrentHashMap虽然也是基于散列的map,但他使用了一种完全不同的加锁策略来提供并发性,ConcurrentHashMap并不把所有的方法都在同一个锁上进行同步并使只能有一个线程访问容器。而是使用一种粒度更细的加锁机制来实现更大程度的共享。与HashTable和synchronizedMap相比,ConcurrentHaspMap具有更多的优势,只有在程序需要加锁map以进行独占访问时,我才放弃使用ConcurrentHashMap。
ConcurrentHashMap接口
package java.util.concurrent; import java.util.Map; /** * @since 1.5 * @author Doug Lea * @param <K> the type of keys maintained by this map * @param <V> the type of mapped values */ public interface ConcurrentMap<K, V> extends Map<K, V> { //如果K没有对应的映射值 才插入 V putIfAbsent(K key, V value); //仅当K值被映射到V时才移除 boolean remove(Object key, Object value); //仅当K被映射到oldValue时才替换newValue boolean replace(K key, V oldValue, V newValue); //仅当K值被映射到V时才移除 替换 V replace(K key, V value); }
2.CopyOnWriteListArrayList
它用于替代同步list,在某些情况下能够提供更好的并发性能,从字面意思可以看出,在每次修改时,都会创建并重新发布一个新的容器版本,从而实现可变性,“写入时复制”容器的迭代器保留一个执行底层基础数组的引用,这个数组当前位于迭代器的其实位置,由于它不会被修改,一次在对其进行同步时只需确保数组内容的可见性。一次多线程可以同时对这个容器进行迭代,而不会彼此干扰或者与修改容器的线程相互干扰。很显然,每次修改容器都要复制底层数组,这需要一定的开销,特别是当容器的规模较大时。因此,他的应用场景主要在迭代操作远远多余修改操作时,一些事件监听系统,在分发通知都需要迭代已经注册监听器表,并且调用每个监听器,而注册新的监听器和取消监听器这种操作很少,这种场景就非常适合使用使用CopyOnWriteListArrayList。
3.BlockingQueue 实现(LinkedBlockingQueue,ArrayBlockinQueue,SynchronousQueue)
阻塞队列,提供了可阻塞的put和take方法,如果队列慢了,那么put就会阻塞,直到队列有空间可用,如果队列为空,那么take方法就会阻塞,直到队列有元素可用,可以利用阻塞队列实现生产者-和消费者模式。
引用场景,使用多线程处理批量任务时候,可使用BlockingQueue,这里比较特使的SynchronousQueue,
它实际上不是一个真正的队列,因为不会为队列内元素维护存储空间,与其他队列不同的是,它维护一组线程,而这些线程等待把元素加入和移除队列,这样就没有入列和出列的操作了,而这个队列put,take会一直阻塞,直到另一个线程准备好获取交付的工作时
附加一个文件模拟搜索程序demo:
生产者遍历文件并加入队列,消费者取出文件名称对它建立索引便于后面访问。生产者遍历文件
public class FileSearch implements Runnable { private final BlockingQueue<File> fileQueue; private final FileFilter fileFilter; private final File root; .... public void run() { try { search(root); }catch (InterruptedException e){ //恢复被中断的状态 Thread.currentThread().interrupt(); } } private void search(File root){ File[] entries = root.listFiles(fileFilter); if (entries!=null){ for(File entry :entries){ if(entry.isDirectory()){ search(root); }else if(!alreadyIndexed(entry)){ fileQueue.put(entry); } } } } }
消费者加索引
public class Indexerimplements Runnable { private final BlockingQueue<File> queue; public Indexer(BlockingQueue<File> queue){ this.queue=queue; } public void run() { try { while (true){ indexFile(queue.take()); } }catch (InterruptedException e){ Thread.currentThread().interrupt(); } } }
以上两段伪代码,是对阻塞队列的使用
相关推荐
Java 并发集合:ConcurrentHashMap 和 ...Java 并发集合(ConcurrentHashMap 和 BlockingQueue)提供了高效的并发操作和线程安全机制,广泛应用于多种场景,例如多线程编程、数据存储和访问、生产者-消费者模式等。
【Java 多线程与并发】并发集合类`ConcurrentHashMap`是Java程序设计中一个重要的工具,尤其在高并发场景下,它提供了高效的线程安全。`ConcurrentHashMap`在JDK 1.7和1.8中有着显著的区别。 在JDK 1.7中,`...
—深入解析ConcurrentHashMap-慕课专栏.html" 和 "25 经典并发容器,多线程面试必备—深入解析ConcurrentHashMap下-慕课专栏.html":这两篇文章深入探讨了Java并发容器中的`ConcurrentHashMap`,它是线程安全的哈希...
4. **并发容器**:除了基础的并发工具,Aduna Commons Concurrent还提供了一些并发友好的容器,如ConcurrentHashMap、CopyOnWriteArrayList等,这些容器在多线程环境下能够保证操作的线程安全,减少了开发者对同步...
- 并发工具类:了解ConcurrentHashMap、CountDownLatch、CyclicBarrier、Semaphore等并发工具的用法。 4. **框架** - Spring框架:理解依赖注入(DI)和面向切面编程(AOP),掌握Spring MVC和Spring Boot的应用...
在探索多线程和设计模式的同时,还要关注线程间的通信(如使用`wait()`、`notify()`、`notifyAll()`等)、同步机制(如`synchronized`关键字、`Lock`接口等)、线程池的使用(`ExecutorService`、`...
【Java并发容器之ConcurrentHashMap】是Java编程中用于高效并发操作的重要工具。相比于HashMap,ConcurrentHashMap在多线程环境下提供了线程安全的保证,避免了因扩容导致的CPU资源消耗过高问题。传统的线程安全解决...
Java并发编程是Java开发中的重要领域,涉及到多线程、并发控制、同步机制等多个知识点。以下是对Java并发知识体系的详细解析。 首先,我们要理解并发的理论基础。并发是为了提高系统资源利用率和处理能力,让多个...
【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...
- **线程安全**:如果一段代码或对象在多线程环境中被多个线程并发访问时,能够保证正确的执行结果,即不会因为线程间的竞争导致数据不一致或程序错误,则这段代码或对象称为线程安全的。 - **`Vector`**:`Vector`...
- 使用HashMap和ConcurrentHashMap构建缓存,线程安全。 - 结合FutureTask实现异步加载和缓存。 17. **CompletionService** - 提供一种方式,一旦任务完成,就获取并处理结果。 18. **线程服务的优雅停止** - ...
通过线程池,我们可以限制并发线程的数量,避免过度消耗系统资源。 2. **并发容器**:Java的`ConcurrentHashMap`、`CopyOnWriteArrayList`等并发容器提供线程安全的数据结构,使得多个线程可以安全地共享数据,而...
Collections 部分提供了一些并发集合类,例如 CopyOnWriteArrayList、ConcurrentHashMap 等,这些类可以在多线程环境下安全地使用。 3.Atomic: Atomic 部分提供了一些原子类,例如 AtomicInteger、AtomicLong 等...
线程是操作系统调度的基本单位,它允许在一个进程中并发地执行多个任务。在Java中,线程的创建主要有两种方式:一是继承`Thread`类,二是实现`Runnable`接口。由于Java不支持多重继承,因此使用`Runnable`接口更加...
2. **集合框架**:可能包含对ArrayList、LinkedList、HashSet、HashMap等集合类的高级用法,比如泛型、迭代器、并发容器如ConcurrentHashMap的使用。 3. **IO/NIO/BIO**:Java的输入输出流、非阻塞I/O和生物I/O在...
5. **线程池**:`ExecutorService`和`ThreadPoolExecutor`是Java提供的线程池管理工具,可以有效控制并发线程的数量,避免频繁创建和销毁线程带来的开销。线程池通过设置核心线程数、最大线程数、线程存活时间等参数...
1. **线程安全**:在Java并发编程中,线程安全是指在多线程环境下,代码能够正确地处理多个线程的访问,不会出现数据不一致或竞态条件。例如,书中可能会展示如何使用`synchronized`关键字、`volatile`变量以及`...
4. **并发容器**:特定的并发容器(如Java的`ConcurrentHashMap`或C++的`std::mutex`保护的容器)设计用于在多线程环境下安全地存储和访问数据。 5. **调度策略**:工具可能包含线程调度策略,如优先级调度、时间片...
7. **线程池**:`ExecutorService`允许创建线程池,可以有效地管理和控制并发线程的数量,避免过多线程导致的系统资源浪费。 8. **线程通信**:Java提供了`wait()`, `notify()`, `notifyAll()`方法进行线程间的通信...