Improve EventBus by removing read locking.
This is primarily done by using ConcurrentHashMap, which has lock-free reads and thread-contention-based writes. Only one thread at a time can register threads, however, as baking events isn't thread safe (and there's no reason to make it thread-safe anyway). My own benchmarks indicate 1.4-2.2 million operations/ms throughput and approximately ~1ns/event post for four threads posting events.
This commit is contained in:
parent
bd07be8772
commit
59208aad86
@ -9,8 +9,9 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -18,8 +19,8 @@ public class EventBus
|
|||||||
{
|
{
|
||||||
|
|
||||||
private final Map<Class<?>, Map<Byte, Map<Object, Method[]>>> byListenerAndPriority = new HashMap<>();
|
private final Map<Class<?>, Map<Byte, Map<Object, Method[]>>> byListenerAndPriority = new HashMap<>();
|
||||||
private final Map<Class<?>, EventHandlerMethod[]> byEventBaked = new HashMap<>();
|
private final Map<Class<?>, EventHandlerMethod[]> byEventBaked = new ConcurrentHashMap<>();
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
private final Lock lock = new ReentrantLock();
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
public EventBus()
|
public EventBus()
|
||||||
@ -34,15 +35,7 @@ public class EventBus
|
|||||||
|
|
||||||
public void post(Object event)
|
public void post(Object event)
|
||||||
{
|
{
|
||||||
EventHandlerMethod[] handlers;
|
EventHandlerMethod[] handlers = byEventBaked.get( event.getClass() );
|
||||||
lock.readLock().lock();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
handlers = byEventBaked.get( event.getClass() );
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( handlers != null )
|
if ( handlers != null )
|
||||||
{
|
{
|
||||||
@ -103,7 +96,7 @@ public class EventBus
|
|||||||
public void register(Object listener)
|
public void register(Object listener)
|
||||||
{
|
{
|
||||||
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
||||||
lock.writeLock().lock();
|
lock.lock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
||||||
@ -129,14 +122,14 @@ public class EventBus
|
|||||||
}
|
}
|
||||||
} finally
|
} finally
|
||||||
{
|
{
|
||||||
lock.writeLock().unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregister(Object listener)
|
public void unregister(Object listener)
|
||||||
{
|
{
|
||||||
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
||||||
lock.writeLock().lock();
|
lock.lock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
||||||
@ -165,7 +158,7 @@ public class EventBus
|
|||||||
}
|
}
|
||||||
} finally
|
} finally
|
||||||
{
|
{
|
||||||
lock.writeLock().unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +195,7 @@ public class EventBus
|
|||||||
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) );
|
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) );
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
byEventBaked.put( eventClass, null );
|
byEventBaked.remove( eventClass );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user