final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
*/
volatile boolean active;
//之后为构造器以及覆写的equal和hashCode方法。
...
}
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class> eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
//之后为构造器以及覆写的equal和hashCode方法。
...
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, Object> entry : entries) {
Class> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
/**
* Called from a subscriber's event handling method, further event delivery will be canceled. Subsequent
* subscribers
* won't receive the event. Events are usually canceled by higher priority subscribers (see
* {@link Subscribe#priority()}). Canceling is restricted to event handling methods running in posting thread
* {@link ThreadMode#POSTING}.
*/
public void cancelEventDelivery(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
if (!postingState.isPosting) {
throw new EventBusException(
"This method may only be called from inside event handling methods on the posting thread");
} else if (event == null) {
throw new EventBusException("Event may not be null");
} else if (postingState.event != event) {
throw new EventBusException("Only the currently handled event may be aborted");
} else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {
throw new EventBusException(" event handlers may only abort the incoming event");
}
postingState.canceled = true;
}
/**
* Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
* event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
*/
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
/**
* Remove and gets the recent sticky event for the given event type.
*
* @see #postSticky(Object)
*/
public T removeStickyEvent(Class eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.remove(eventType));
}
}
/**
* Removes the sticky event if it equals to the given event.
*
* @return true if the events matched and the sticky event was removed.
*/
public boolean removeStickyEvent(Object event) {
synchronized (stickyEvents) {
Class> eventType = event.getClass();
Object existingEvent = stickyEvents.get(eventType);
if (event.equals(existingEvent)) {
stickyEvents.remove(eventType);
return true;
} else {
return false;
}
}
}
/**
* Removes all sticky events.
*/
public void removeAllStickyEvents() {
synchronized (stickyEvents) {
stickyEvents.clear();
}
}
这几个方法都比较容易理解,不再解释了,最后关于sticky还有一个get方法,如下:
/**
* Gets the most recent sticky event for the given type.
*
* @see #postSticky(Object)
*/
public T getStickyEvent(Class eventType) {
synchronized (stickyEvents) {
return eventType.cast(stickyEvents.get(eventType));
}
}
<script language="javascript">
$(function (){
var i = 4;$(window).bind("scroll", function (event){
//滚动条到网页头部的 高度,兼容ie,ff,chrome
var top = document.documentElement.s
包冲突是开发过程中很常见的问题:
其表现有:
1.明明在eclipse中能够索引到某个类,运行时却报出找不到类。
2.明明在eclipse中能够索引到某个类的方法,运行时却报出找不到方法。
3.类及方法都有,以正确编译成了.class文件,在本机跑的好好的,发到测试或者正式环境就
抛如下异常:
java.lang.NoClassDefFoundError: Could not in
NAME: gpasswd - administer the /etc/group file
SYNOPSIS:
gpasswd group
gpasswd -a user group
gpasswd -d user group
gpasswd -R group
gpasswd -r group
gpasswd [-A user,...] [-M user,...] g
enquiry mysql version in centos linux
yum list installed | grep mysql
yum -y remove mysql-libs.x86_64
enquiry mysql version in yum repositoryyum list | grep mysql oryum -y list mysql*
install mysq
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
select p.spid,c.object_name,b.session_id,b.oracle_username,b.os_user_name from v$process p,v$session a, v$locked_object b,all_objects c where p.addr=a.paddr and a.process=b.process and c.object_id=b.