Tag: concurrency

最快的方法来初始化ConcurrentHashMap的值

ConcurrentHashMap通常在并发环境中用于在键下聚合某些事件 – 比如计算某些字符串值的命中。 如果我们事先不知道密钥,我们需要有一个很好的方法来初始化密钥的需要,它应该是快速和安全的并发性。 这个问题的最佳模式(就效率而言)是多少? 我将使用模型映射与声明如下: ConcurrentHashMap map = new ConcurrentHashMap(); 但它可能是一个包含任何键值对的映射,如果键中的键尚未存在,则需要初始化键值对,并将值状态变为记录事件。 有两种流行的方法:第一种使用ConcurrentHashMap.putIfAbsent : AtomicInteger count = map.get(s); if (count == null) { count = new AtomicInteger(0); AtomicInteger prevCount = map.putIfAbsent(s, count); if (prevCount != null) { count = prevCount; } } count.incrementAndGet(); 第二个使用ConcurrentHashMap.computeIfAbsent : AtomicInteger count = map.computeIfAbsent(s, (k) -> new AtomicInteger(0)); count.incrementAndGet(); 哪一个更适合这项任务? […]

如何使Spring JMSListener突发到最大并发线程?

我有一个使用ActiveMQ版本5.10的Spring JMS应用程序。 我正在执行简单的并发测试。 我使用Spring Boot,当前版本和注释来配置JMSListener和消息生成器。 消息生产者只是尽可能快地在队列上抛出消息。 消息侦听器将消息从队列中拉出,但在获取消息后hibernate1秒钟 – 模拟消息侦听器在获取消息后需要执行的一些工作。 我将JMSListener设置为100-1000个并发线程。 如果我同时启动消息生产者和消费者(都在他们自己的JVM中运行),即使最大范围设置为1000,消费者也永远不会超过最小配置的线程。 如果我让生产者首先启动并在队列上放置几千条消息,然后启动一个或多个消费者实例,它将稳定地提升线程,从100开始,然后每秒20个左右的线程,直到达到状态队列中有大约20-30条消息在飞行中。 它永远不会捕获生成器 – 即使消费者没有接近其maxConcurrency计数,也总会有一些消息在队列中。 为什么消息使用者没有突然进入一堆额外的线程来清空队列而不是让队列中有20-30条消息呢? 消费者是否有办法继续快速添加线程以赶上队列中的消息? 以下是代码的相关部分。 消息制作者 @Component public class ClientServiceImpl implements ClientService { private static final String QUEUE=”message.test.queue”; @Autowired private JmsTemplate jmsTemplate; @Override public void submitMessage(ImportantMessage importantMessage) { System.out.println(“*** Sending ” + importantMessage); jmsTemplate.convertAndSend(QUEUE, importantMessage); } } 消息消费者 @SpringBootApplication @EnableJms public class […]

Java并发:“级联”变量中的易失性与最终性?

是 final Map<Integer,Map> status = new ConcurrentHashMap<Integer, Map>(); Map<Integer,Map> statusInner = new ConcurrentHashMap<Integer, Map>(); status.put(key,statusInner); 同样的 volatile Map<Integer,Map> status = new ConcurrentHashMap<Integer, Map>(); Map<Integer,Map> statusInner = new ConcurrentHashMap<Integer, Map>(); status.put(key,statusInner); 如果内部Map由不同的线程访问? 或者甚至是这样的要求: volatile Map<Integer,Map> status = new ConcurrentHashMap<Integer, Map>(); volatile Map<Integer,Map> statusInner = new ConcurrentHashMap<Integer, Map>(); status.put(key,statusInner); 如果它不是“级联”映射,则final和volatile最终会产生相同的效果,即所有线程总是看到Map的正确内容……但是如果Map iteself包含一个map,会发生什么?如示例中所示…如何使内部地图正确“内存瘫痪”? 坦克! 汤姆

RxJava – 调度程序与ExecutorService?

我有一种预感,对于RxJava中的高度计算,并行化的任务,传统的ExecutorService会比Scheduler更快。 我有一个理论认为这个代码 Observable source = … source.flatMap(myItem -> myItem.process().subscribeOn(Schedulers.computation())) .subscribe(); 会跑得比这慢 final ExecutorService svc = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1); Observable source = … source.flatMap(myItem -> myItem.process().subscribeOn(Schedulers.from(svc))) .finallyDo(svc::shutdown) .subscribe(); 我将这两种方法与我在工作中进行的典型并行处理进行了比较,得到了以下结果。 EXECUTOR START: 2016-01-25T09:47:04.350 END: 2016-01-25T09:48:37.181 TOTAL TIME (SEC): 92 COMPUTATION SCHEDULER START: 2016-01-25T09:50:37.799 END: 2016-01-25T09:54:23.674 TOTAL TIME (SEC): 225 所以我的粗略测试表明,传统的ExecutorService比Scheduler快得多。 这些结果有原因吗? RxJava调度程序是否未针对并行化进行优化? 我的印象是计算调度程序使用的线程比执行程序少。

同步块可以比Atomics更快吗?

假设有以下两个计数器实现: class Counter { private final AtomicInteger atomic = new AtomicInteger(0); private int i = 0; public void incrementAtomic() { atomic.incrementAndGet(); } public synchronized void increment() { i++; } } 乍一看,primefaces应该更快,更具可扩展性。 我相信他们是。 但它们是否比synchronized块一样快? 或者当该规则被破坏时存在某些情况(例如SMP /单CPU机器,不同的CPU ISA,OS等)?

在期货清单上流式传输的最有效方式

我通过流式传输对象列表来调用异步客户端方法。 该方法返回Future。 迭代调用后返回的Futures列表的最佳方法是什么(以便处理那些首先出现的Future)? 注意:异步客户端仅返回Future not CompletableFuture。 以下是代码: List<Future> listOfFuture = objectsToProcess.parallelStream() .map((object) -> { /* calling an async client returning a Future */ }) .collect(Collectors.toList());

可重置的倒计时补丁

我需要的东西直接等同于CountDownLatch ,但是可以重置(保持线程安全!)。 我不能使用经典的同步结构,因为它们在这种情况下根本不起作用(复杂的锁定问题)。 目前,我正在创建许多CountDownLatch对象,每个对象都替换前一个。 我相信这是在GC中的年轻一代(由于物体数量庞大)。 您可以看到使用下面的锁存器的代码(它是用于ns-3网络模拟器接口的java.net模拟的一部分)。 一些想法可能是尝试CyclicBarrier (JDK5 +)或Phaser (JDK7) 我可以测试代码并回到找到解决此问题的任何人,因为我是唯一可以将其插入正在运行的系统中以查看发生了什么的人:) /** * */ package kokunet; import java.io.IOException; import java.nio.channels.ClosedSelectorException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import kokuks.IConnectionSocket; import kokuks.KKSAddress; import kokuks.KKSSocket; import kokuks.KKSSocketListener; /** * KSelector * @version 1.0 * @author Chris Dennett */ public class KSelector extends SelectorImpl { // True […]

单例类方法的并发调用

我有一个单身人士class: public class Singleton { private static Singleton istance = null; private Singleton() {} public synchronized static Singleton getSingleton() { if (istance == null) istance = new Singleton(); return istance; } public void work(){ for(int i=0; i<10000; i++){ Log.d("———–", ""+i); } } } 并且多个线程正在调用work()函数: public class Main { public static void main(String[] args) { new […]

ConcurrentHashMap JDK 8何时使用computeIfPresent

jdk 8的新版Concurrent Hash Map有两个新方法。 computeIfAbsent computeIfPresent putIfAbsent – 旧方法 我理解putIfAbsent和computeIfAbsent的用例。 但我不确定何时使用computeIfPresent 。 另外,如果我现在有computeIfPresent,为什么还需要putIfAbsent。 putIfAbsent会创建至少一个额外的值实例。 原因只是具有向后兼容性吗?

java.lang.Class方法是否安全?

在IBM JVM下,当多个线程试图在不同对象上同时调用Class.getAnnotation时(但具有相同的注释),我们遇到了一个问题。 线程开始在Hashtable内的监视器上等待死锁,Hashtable用作IBM JVM中注释的缓存。 最奇怪的是,持有此监视器的线程在Hashtable.get内部进入“等待状态”状态,使所有其他线程无限期地等待。 IBM的支持表示,Class.getAnnotation的实现不是线程安全的。 与其他JVM实现(例如,OpenJDK)相比,我们看到它们以线程安全的方式实现了Class方法。 IBM JVM是一个封闭的源JVM,它们确实与它们的JVM一起发布了一些源代码,但是只要它们的Class实现是线程安全的,它就不足以做出明确的判断。 只要其方法是线程安全的,Class文档就不会明确说明。 因此,将类方法(特别是getAnnotation)视为线程安全或者我们必须在multithreading环境中使用同步块是一种安全的假设吗? 流行的框架(例如Hibernate)如何减轻这个问题? 我们在使用getAnnotation方法的Hibernate代码中没有发现任何同步用法。