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.lang.reflect.Constructor;
22  import java.util.concurrent.Executor;
23  import java.util.concurrent.RejectedExecutionException;
24  
25  import org.eclipse.jetty.util.Loader;
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  import org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume;
29  
30  /**
31   * <p>An {@link ExecutionStrategy} executes {@link Runnable} tasks produced by a {@link Producer}.
32   * The strategy to execute the task may vary depending on the implementation; the task may be
33   * run in the calling thread, or in a new thread, etc.</p>
34   * <p>The strategy delegates the production of tasks to a {@link Producer}, and continues to
35   * execute tasks until the producer continues to produce them.</p>
36   */
37  public interface ExecutionStrategy
38  {
39      /**
40       * <p>Initiates (or resumes) the task production and execution.</p>
41       * <p>This method guarantees that the task is never run by the
42       * thread that called this method.</p>
43       *
44       * @see #execute()
45       */
46      public void dispatch();
47  
48      /**
49       * <p>Initiates (or resumes) the task production and execution.</p>
50       * <p>The produced task may be run by the same thread that called
51       * this method.</p>
52       *
53       * @see #dispatch()
54       */
55      public void execute();
56  
57      /**
58       * A task that can handle {@link RejectedExecutionException}
59       */
60      public interface Rejectable
61      {
62          public void reject();
63      }
64  
65      /**
66       * <p>A producer of {@link Runnable} tasks to run.</p>
67       * <p>The {@link ExecutionStrategy} will repeatedly invoke {@link #produce()} until
68       * the producer returns null, indicating that it has nothing more to produce.</p>
69       * <p>When no more tasks can be produced, implementations should arrange for the
70       * {@link ExecutionStrategy} to be invoked again in case an external event resumes
71       * the tasks production.</p>
72       */
73      public interface Producer
74      {
75          /**
76           * <p>Produces a task to be executed.</p>
77           *
78           * @return a task to executed or null if there are no more tasks to execute
79           */
80          Runnable produce();
81      }
82      
83      
84      /**
85       * <p>A factory for {@link ExecutionStrategy}.</p>
86       */
87      public static interface Factory
88      {
89          /**
90           * <p>Creates a new {@link ExecutionStrategy}.</p>
91           *
92           * @param producer the execution strategy producer
93           * @param executor the execution strategy executor
94           * @return a new {@link ExecutionStrategy}
95           */
96          public ExecutionStrategy newExecutionStrategy(Producer producer, Executor executor);
97  
98          /**
99           * @return the default {@link ExecutionStrategy}
100          */
101         public static Factory getDefault()
102         {
103             return DefaultExecutionStrategyFactory.INSTANCE;
104         }
105 
106         /**
107          * @param producer the execution strategy producer
108          * @param executor the execution strategy executor
109          * @deprecated use {@code getDefault().newExecutionStrategy(Producer, Executor)} instead
110          */
111         @Deprecated
112         public static ExecutionStrategy instanceFor(Producer producer, Executor executor)
113         {
114             return getDefault().newExecutionStrategy(producer, executor);
115         }
116     }
117 
118     public static class DefaultExecutionStrategyFactory implements Factory
119     {
120         private static final Logger LOG = Log.getLogger(Factory.class);
121         private static final Factory INSTANCE = new DefaultExecutionStrategyFactory();
122 
123         @Override
124         public ExecutionStrategy newExecutionStrategy(Producer producer, Executor executor)
125         {
126             String strategy = System.getProperty(producer.getClass().getName() + ".ExecutionStrategy");
127             if (strategy != null)
128             {
129                 try
130                 {
131                     Class<? extends ExecutionStrategy> c = Loader.loadClass(producer.getClass(), strategy);
132                     Constructor<? extends ExecutionStrategy> m = c.getConstructor(Producer.class, Executor.class);
133                     LOG.info("Use {} for {}", c.getSimpleName(), producer.getClass().getName());
134                     return m.newInstance(producer, executor);
135                 }
136                 catch (Exception e)
137                 {
138                     LOG.warn(e);
139                 }
140             }
141 
142             return new ExecuteProduceConsume(producer, executor);
143         }
144     }
145 }