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      /**
59       * A task that can handle {@link RejectedExecutionException}
60       */
61      public interface Rejectable
62      {
63          public void reject();
64      }
65      
66      /**
67       * <p>A producer of {@link Runnable} tasks to run.</p>
68       * <p>The {@link ExecutionStrategy} will repeatedly invoke {@link #produce()} until
69       * the producer returns null, indicating that it has nothing more to produce.</p>
70       * <p>When no more tasks can be produced, implementations should arrange for the
71       * {@link ExecutionStrategy} to be invoked again in case an external event resumes
72       * the tasks production.</p>
73       */
74      public interface Producer
75      {
76          /**
77           * <p>Produces a task to be executed.</p>
78           *
79           * @return a task to executed or null if there are no more tasks to execute
80           */
81          Runnable produce();
82      }
83  
84      public static class Factory
85      {
86          private static final Logger LOG = Log.getLogger(Factory.class);
87  
88          public static ExecutionStrategy instanceFor(Producer producer, Executor executor)
89          {
90              // TODO remove this mechanism before release
91              String strategy = System.getProperty(producer.getClass().getName()+".ExecutionStrategy");
92              if (strategy!=null)
93              {
94                  try
95                  {
96                      Class<? extends ExecutionStrategy> c = Loader.loadClass(producer.getClass(),strategy);
97                      Constructor<? extends ExecutionStrategy> m = c.getConstructor(Producer.class,Executor.class);
98                      LOG.info("Use {} for {}",c.getSimpleName(),producer.getClass().getName());
99                      return  m.newInstance(producer,executor);
100                 }
101                 catch(Exception e)
102                 {
103                     LOG.warn(e);
104                 }
105             }
106             
107             return new ExecuteProduceConsume(producer,executor);
108         }
109     }
110 }