📄 schedulerservice.java
字号:
/*
* Copyright (c) 2001 Sun Microsystems, Inc. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Sun Microsystems, Inc. for Project JXTA."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact Project JXTA at http://www.jxta.org.
*
* 5. Products derived from this software may not be called "JXTA",
* nor may "JXTA" appear in their name, without prior written
* permission of Sun.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Project JXTA. For more
* information on Project JXTA, please see
* <http://www.jxta.org/>.
*
* This license is based on the BSD license adopted by the Apache Foundation.
*
* $Id: SchedulerService.java,v 1.9 2002/05/16 05:55:46 bondolo Exp $
*/
package net.jxta.impl.cm;
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import net.jxta.impl.util.TimeUtils;
/**
* Description of the Class
*
* THIS CLASS MUST NOT CALL ANYTHING OUTSIDE ITSELF WHILE SYNCHRONIZED.
* To avoid dealocks we maintain strick layering of sycnh. This is in layer 0.
* The indexer is in layer 0 too.
* The file expiration service is layer 1.
* The cm is layer 2.
*/
public class SchedulerService implements Runnable {
static final Category LOG = Category.getInstance(SchedulerService.class.getName());
volatile boolean done;
SchedulerPriorityQueue heap;
/**
* Constructor for the SchedulerService object
*/
public SchedulerService() {
this.done = false;
this.heap = new SchedulerPriorityQueue( 1024, 2 );
}
public synchronized void stop() {
done = true;
notifyAll();
}
/**
* Description of the Method
*
*@param action Description of Parameter
*@param timeout time at which the action will take place expressed in
* milliseconds relative to the current time.
*@return The pending action. Can only be used for cancel since
* it may have *already* been performed by the time scheduleAction returns
*/
public synchronized PendingAction scheduleAction( Action action,
long timeout ) {
long actionAt = TimeUtils.toAbsoluteTimeMillis( timeout );
PendingAction el = new PendingAction( action, actionAt );
heap.put( el );
if ( heap.top() == el ) {
notify();
}
return el;
}
/**
* Description of the Method
*
* cancel does not call anything outside and is not synchronized.
* all synchro is provided here. PendingAction.cancel is *not* a
* public method.
*
* @param pendingAction Description of Parameter
*/
private synchronized void doCancel( PendingAction pendingAction ) {
// Try and cancel if it is not too late.
pendingAction.cancel();
// Cancel may not do anything if it was no-longer cancellable
// because it has been poped from the queue already and is about
// to be performed (which happens out of synchronized).
// In that case, head.top() cannot be equal to pending action
// and thus we can execute the following without checking any
// further.
if ( heap.top() == pendingAction ) {
notify();
}
}
/**
* Description of the Method
*
* The part that affects the queue is done in doCancel.
* The main task of this routine is to make sure that perform
* may never happen or finish after cancelAction returns.
*
* @param pendingAction Description of Parameter
*/
public void cancelAction( PendingAction pendingAction ) {
// Do the part of cancel that affects the queue.
doCancel(pendingAction);
// Make sure that if perform beat us to the finish line
// then it is actually finished.
pendingAction.noPerform();
}
/**
* Main processing method for the SchedulerService object
*/
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while ( !done ) {
PendingAction e = getNextEvent();
if ( done ) break;
try {
e.perform( this );
} catch ( Exception ex ) {
ex.printStackTrace();
}
Thread.yield();
}
}
/**
* Gets the nextEvent attribute of the SchedulerService object
*
*@return The nextEvent value
*/
private synchronized PendingAction getNextEvent() {
PendingAction el;
long timeout;
// Currently no-one sets done from the outside, but that could
// change.
if ( done ) {
return null;
} else if ( ( el = (PendingAction) heap.top() ) == null ) {
timeout = Long.MAX_VALUE;
} else {
timeout = TimeUtils.toRelativeTimeMillis( el.time );
}
while ( !done ) {
try {
if ( timeout > 0 ) {
wait( timeout );
}
if ( done )
// we were stopped
break;
if ( el != heap.top() ) {
// new minimum element inserted
el = (PendingAction) heap.top();
timeout = TimeUtils.toRelativeTimeMillis( el.time );
} else {
// we were woken up to act
heap.pop();
el.nonCancelable();
return el;
}
} catch ( InterruptedException e ) {
Thread.interrupted(); // yes sir, I am awake. I wasn't asleep, no sir!
continue;
}
}
return null;
}
/**
* Description of the Class
*/
public class PendingAction {
SchedulerService.Action action;
boolean cancelable = true;
long time;
/**
* Constructor for the PendingAction object
*
*@param action the action to perfrom.
*@param time absolute time in milliseconds at which to perform it.
*/
PendingAction( SchedulerService.Action action, long time ) {
this.action = action;
this.time = time;
}
/**
* Gets the time attribute of the PendingAction object
*
*@return The time value
*/
public long getTime() {
return time;
}
/**
* Description of the Method
*
*@param ss Description of Parameter
*/
void perform( SchedulerService ss ) throws Exception {
// Although this method is invoked out of synchronized
// we can trust the stability of action because it cannot
// be cleared after this PendingAction has been poped off
// the queue. PendingActions are poped off the queue
// and made uncancelable under synchronized, and then
// perform() is invoked out of synchronized.
if ( action != null ) {
try {
action.perform( ss );
} finally { // Make sure we do this.
// The following is to permit cancellers to wait
// for perform to done. So that it is garanteed
// that performing the action can in no-way extend
// past the return from cancel, even if cancel was
// too late.
synchronized(this) {
action = null;
notifyAll();
}
}
}
}
/**
* Prevent cancellation
* This is invoked under synchronized after poping this
* PendingAction off the Queue and before calling perform.
*/
void nonCancelable() {
cancelable = false;
}
/**
* Cancel if we still can
*/
void cancel() {
// We must check if this action is cancelable first.
// If this action has already been poped off the queue
// then it may be in the process or about to be "performed"
// (which happens out of synchronized). In that case we
// must not clear cancel lest we create an NPE.
if (cancelable) {
action = null;
}
}
/**
* makes sure that any perform that might have been going on
* while we were trying to cancel either did not occur (cancel
* worked and set action to null) or is finished (and
* perform set action to null)
*/
synchronized void noPerform() {
try {
while (action != null) {
wait();
}
} catch (InterruptedException intr) {
// Just return then.
}
}
}
/**
* Description of the Class
*/
class SchedulerPriorityQueue extends PriorityQueue {
/**
* Constructor for the SchedulerPriorityQueue object
*
* @param heapSize Description of Parameter
* @param increase Description of Parameter
*/
SchedulerPriorityQueue( int heapSize, int increase ) {
super.initialize( heapSize, increase );
}
/**
* Description of the Method
*
* @param o1 Description of Parameter
* @param o2 Description of Parameter
* @return Description of the Returned Value
*/
protected boolean lessThan( Object o1, Object o2 ) {
PendingAction a1 = (PendingAction) o1;
PendingAction a2 = (PendingAction) o2;
return a1.time < a2.time;
}
}
/**
* Description of the Class
*/
public static interface Action {
/**
* called when alarm expires
*
* @param ss the service which called this action so you can reschedule
*/
void perform( SchedulerService ss ) throws Exception;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -