View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util.thread;
20  
21  import java.util.Timer;
22  import java.util.TimerTask;
23  import java.util.concurrent.RejectedExecutionException;
24  import java.util.concurrent.TimeUnit;
25  
26  import org.eclipse.jetty.util.component.AbstractLifeCycle;
27  import org.eclipse.jetty.util.log.Log;
28  import org.eclipse.jetty.util.log.Logger;
29  
30  
31  /* ------------------------------------------------------------ */
32  /** A scheduler based on the the JVM Timer class
33   */
34  public class TimerScheduler extends AbstractLifeCycle implements Scheduler, Runnable
35  {
36      private static final Logger LOG = Log.getLogger(TimerScheduler.class);
37  
38      /*
39       * This class uses the Timer class rather than an ScheduledExecutionService because
40       * it uses the same algorithm internally and the signature is cheaper to use as there are no
41       * Futures involved (which we do not need).
42       * However, Timer is still locking and a concurrent queue would be better.
43       */
44  
45      private final String _name;
46      private final boolean _daemon;
47      private Timer _timer;
48  
49      public TimerScheduler()
50      {
51          this(null, false);
52      }
53  
54      public TimerScheduler(String name, boolean daemon)
55      {
56          _name = name;
57          _daemon = daemon;
58      }
59  
60      @Override
61      protected void doStart() throws Exception
62      {
63          _timer = _name == null ? new Timer() : new Timer(_name, _daemon);
64          run();
65          super.doStart();
66      }
67  
68      @Override
69      protected void doStop() throws Exception
70      {
71          _timer.cancel();
72          super.doStop();
73          _timer = null;
74      }
75  
76      @Override
77      public Task schedule(final Runnable task, final long delay, final TimeUnit units)
78      {
79          Timer timer = _timer;
80          if (timer == null)
81              throw new RejectedExecutionException("STOPPED: " + this);
82          SimpleTask t = new SimpleTask(task);
83          timer.schedule(t, units.toMillis(delay));
84          return t;
85      }
86  
87      @Override
88      public void run()
89      {
90          Timer timer = _timer;
91          if (timer != null)
92          {
93              timer.purge();
94              schedule(this, 1, TimeUnit.SECONDS);
95          }
96      }
97  
98      private static class SimpleTask extends TimerTask implements Task
99      {
100         private final Runnable _task;
101 
102         private SimpleTask(Runnable runnable)
103         {
104             _task = runnable;
105         }
106 
107         @Override
108         public void run()
109         {
110             try
111             {
112                 _task.run();
113             }
114             catch (Throwable x)
115             {
116                 LOG.warn("Exception while executing task " + _task, x);
117             }
118         }
119 
120         @Override
121         public String toString()
122         {
123             return String.format("%s.%s@%x",
124                     TimerScheduler.class.getSimpleName(),
125                     SimpleTask.class.getSimpleName(),
126                     hashCode());
127         }
128     }
129 }