Java

Форк
0
172 строки · 6.6 Кб
1
/*
2
 * Copyright (C) 2012 The Guava Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.google.common.util.concurrent.testing;
18

19
import static java.util.concurrent.TimeUnit.NANOSECONDS;
20

21
import com.google.common.annotations.GwtIncompatible;
22
import com.google.common.collect.ImmutableList;
23
import com.google.common.util.concurrent.AbstractFuture;
24
import com.google.common.util.concurrent.AbstractListeningExecutorService;
25
import com.google.common.util.concurrent.ListenableScheduledFuture;
26
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
27
import com.google.common.util.concurrent.MoreExecutors;
28
import java.util.List;
29
import java.util.concurrent.Callable;
30
import java.util.concurrent.Delayed;
31
import java.util.concurrent.ExecutorService;
32
import java.util.concurrent.ScheduledExecutorService;
33
import java.util.concurrent.ScheduledFuture;
34
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
35
import java.util.concurrent.TimeUnit;
36

37
/**
38
 * Factory methods for {@link ExecutorService} for testing.
39
 *
40
 * @author Chris Nokleberg
41
 * @since 14.0
42
 */
43
@GwtIncompatible
44
public final class TestingExecutors {
45
  private TestingExecutors() {}
46

47
  /**
48
   * Returns a {@link ScheduledExecutorService} that never executes anything.
49
   *
50
   * <p>The {@code shutdownNow} method of the returned executor always returns an empty list despite
51
   * the fact that everything is still technically awaiting execution. The {@code getDelay} method
52
   * of any {@link ScheduledFuture} returned by the executor will always return the max long value
53
   * instead of the time until the user-specified delay.
54
   */
55
  public static ListeningScheduledExecutorService noOpScheduledExecutor() {
56
    return new NoOpScheduledExecutorService();
57
  }
58

59
  /**
60
   * Creates a scheduled executor service that runs each task in the thread that invokes {@code
61
   * execute/submit/schedule}, as in {@link CallerRunsPolicy}. This applies both to individually
62
   * submitted tasks and to collections of tasks submitted via {@code invokeAll}, {@code invokeAny},
63
   * {@code schedule}, {@code scheduleAtFixedRate}, and {@code scheduleWithFixedDelay}. In the case
64
   * of tasks submitted by {@code invokeAll} or {@code invokeAny}, tasks will run serially on the
65
   * calling thread. Tasks are run to completion before a {@code Future} is returned to the caller
66
   * (unless the executor has been shutdown).
67
   *
68
   * <p>The returned executor is backed by the executor returned by {@link
69
   * MoreExecutors#newDirectExecutorService} and subject to the same constraints.
70
   *
71
   * <p>Although all tasks are immediately executed in the thread that submitted the task, this
72
   * {@code ExecutorService} imposes a small locking overhead on each task submission in order to
73
   * implement shutdown and termination behavior.
74
   *
75
   * <p>Because of the nature of single-thread execution, the methods {@code scheduleAtFixedRate}
76
   * and {@code scheduleWithFixedDelay} are not supported by this class and will throw an
77
   * UnsupportedOperationException.
78
   *
79
   * <p>The implementation deviates from the {@code ExecutorService} specification with regards to
80
   * the {@code shutdownNow} method. First, "best-effort" with regards to canceling running tasks is
81
   * implemented as "no-effort". No interrupts or other attempts are made to stop threads executing
82
   * tasks. Second, the returned list will always be empty, as any submitted task is considered to
83
   * have started execution. This applies also to tasks given to {@code invokeAll} or {@code
84
   * invokeAny} which are pending serial execution, even the subset of the tasks that have not yet
85
   * started execution. It is unclear from the {@code ExecutorService} specification if these should
86
   * be included, and it's much easier to implement the interpretation that they not be. Finally, a
87
   * call to {@code shutdown} or {@code shutdownNow} may result in concurrent calls to {@code
88
   * invokeAll/invokeAny} throwing RejectedExecutionException, although a subset of the tasks may
89
   * already have been executed.
90
   *
91
   * @since 32.0.0 (taking the place of a method with a different return type from 15.0)
92
   */
93
  public static ListeningScheduledExecutorService sameThreadScheduledExecutor() {
94
    return new SameThreadScheduledExecutorService();
95
  }
96

97
  private static final class NoOpScheduledExecutorService extends AbstractListeningExecutorService
98
      implements ListeningScheduledExecutorService {
99

100
    private volatile boolean shutdown;
101

102
    @Override
103
    public void shutdown() {
104
      shutdown = true;
105
    }
106

107
    @Override
108
    public List<Runnable> shutdownNow() {
109
      shutdown();
110
      return ImmutableList.of();
111
    }
112

113
    @Override
114
    public boolean isShutdown() {
115
      return shutdown;
116
    }
117

118
    @Override
119
    public boolean isTerminated() {
120
      return shutdown;
121
    }
122

123
    @Override
124
    public boolean awaitTermination(long timeout, TimeUnit unit) {
125
      return true;
126
    }
127

128
    @Override
129
    public void execute(Runnable runnable) {}
130

131
    @Override
132
    public <V> ListenableScheduledFuture<V> schedule(
133
        Callable<V> callable, long delay, TimeUnit unit) {
134
      return NeverScheduledFuture.create();
135
    }
136

137
    @Override
138
    public ListenableScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
139
      return NeverScheduledFuture.create();
140
    }
141

142
    @Override
143
    public ListenableScheduledFuture<?> scheduleAtFixedRate(
144
        Runnable command, long initialDelay, long period, TimeUnit unit) {
145
      return NeverScheduledFuture.create();
146
    }
147

148
    @Override
149
    public ListenableScheduledFuture<?> scheduleWithFixedDelay(
150
        Runnable command, long initialDelay, long delay, TimeUnit unit) {
151
      return NeverScheduledFuture.create();
152
    }
153

154
    private static class NeverScheduledFuture<V> extends AbstractFuture<V>
155
        implements ListenableScheduledFuture<V> {
156

157
      static <V> NeverScheduledFuture<V> create() {
158
        return new NeverScheduledFuture<>();
159
      }
160

161
      @Override
162
      public long getDelay(TimeUnit unit) {
163
        return Long.MAX_VALUE;
164
      }
165

166
      @Override
167
      public int compareTo(Delayed other) {
168
        return Long.compare(getDelay(NANOSECONDS), other.getDelay(NANOSECONDS));
169
      }
170
    }
171
  }
172
}
173

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.