View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.junitcore.pc;
20  
21  import java.util.Collection;
22  import java.util.concurrent.ExecutorService;
23  import java.util.concurrent.Future;
24  import java.util.concurrent.ThreadPoolExecutor;
25  import java.util.concurrent.TimeUnit;
26  
27  import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
28  
29  /**
30   * Abstract parallel scheduling strategy in private package.
31   * The remaining abstract methods have to be implemented differently
32   * depending if the thread pool is shared with other strategies or not.
33   *
34   * @author Tibor Digana (tibor17)
35   * @see SchedulingStrategy
36   * @see SharedThreadPoolStrategy
37   * @see NonSharedThreadPoolStrategy
38   * @since 2.16
39   */
40  abstract class AbstractThreadPoolStrategy extends SchedulingStrategy {
41      private final ExecutorService threadPool;
42  
43      private final Collection<Future<?>> futureResults;
44  
45      private volatile boolean isDestroyed;
46  
47      AbstractThreadPoolStrategy(ConsoleLogger logger, ExecutorService threadPool) {
48          this(logger, threadPool, null);
49      }
50  
51      AbstractThreadPoolStrategy(ConsoleLogger logger, ExecutorService threadPool, Collection<Future<?>> futureResults) {
52          super(logger);
53          this.threadPool = threadPool;
54          this.futureResults = futureResults;
55      }
56  
57      protected final ExecutorService getThreadPool() {
58          return threadPool;
59      }
60  
61      protected final Collection<Future<?>> getFutureResults() {
62          return futureResults;
63      }
64  
65      @Override
66      public void schedule(Runnable task) {
67          if (canSchedule()) {
68              Future<?> futureResult = threadPool.submit(task);
69              if (futureResults != null) {
70                  futureResults.add(futureResult);
71              }
72          }
73      }
74  
75      @Override
76      protected boolean stop() {
77          boolean wasRunning = disable();
78          if (threadPool.isShutdown()) {
79              wasRunning = false;
80          } else {
81              threadPool.shutdown();
82          }
83          return wasRunning;
84      }
85  
86      @Override
87      protected boolean stopNow() {
88          boolean wasRunning = disable();
89          if (threadPool.isShutdown()) {
90              wasRunning = false;
91          } else {
92              threadPool.shutdownNow();
93          }
94          return wasRunning;
95      }
96  
97      /**
98       * @see Scheduler.ShutdownHandler
99       */
100     @Override
101     protected void setDefaultShutdownHandler(Scheduler.ShutdownHandler handler) {
102         if (threadPool instanceof ThreadPoolExecutor) {
103             ThreadPoolExecutor pool = (ThreadPoolExecutor) threadPool;
104             handler.setRejectedExecutionHandler(pool.getRejectedExecutionHandler());
105             pool.setRejectedExecutionHandler(handler);
106         }
107     }
108 
109     @Override
110     public boolean destroy() {
111         try {
112             if (!isDestroyed) // just an optimization
113             {
114                 disable();
115                 threadPool.shutdown();
116                 this.isDestroyed |= threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
117             }
118             return isDestroyed;
119         } catch (InterruptedException e) {
120             return false;
121         }
122     }
123 }