Java
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
17package com.google.common.util.concurrent.testing;
18
19import static java.util.concurrent.TimeUnit.NANOSECONDS;
20
21import com.google.common.annotations.GwtIncompatible;
22import com.google.common.collect.ImmutableList;
23import com.google.common.util.concurrent.AbstractFuture;
24import com.google.common.util.concurrent.AbstractListeningExecutorService;
25import com.google.common.util.concurrent.ListenableScheduledFuture;
26import com.google.common.util.concurrent.ListeningScheduledExecutorService;
27import com.google.common.util.concurrent.MoreExecutors;
28import java.util.List;
29import java.util.concurrent.Callable;
30import java.util.concurrent.Delayed;
31import java.util.concurrent.ExecutorService;
32import java.util.concurrent.ScheduledExecutorService;
33import java.util.concurrent.ScheduledFuture;
34import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
35import 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
44public final class TestingExecutors {
45private 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*/
55public static ListeningScheduledExecutorService noOpScheduledExecutor() {
56return 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*/
93public static ListeningScheduledExecutorService sameThreadScheduledExecutor() {
94return new SameThreadScheduledExecutorService();
95}
96
97private static final class NoOpScheduledExecutorService extends AbstractListeningExecutorService
98implements ListeningScheduledExecutorService {
99
100private volatile boolean shutdown;
101
102@Override
103public void shutdown() {
104shutdown = true;
105}
106
107@Override
108public List<Runnable> shutdownNow() {
109shutdown();
110return ImmutableList.of();
111}
112
113@Override
114public boolean isShutdown() {
115return shutdown;
116}
117
118@Override
119public boolean isTerminated() {
120return shutdown;
121}
122
123@Override
124public boolean awaitTermination(long timeout, TimeUnit unit) {
125return true;
126}
127
128@Override
129public void execute(Runnable runnable) {}
130
131@Override
132public <V> ListenableScheduledFuture<V> schedule(
133Callable<V> callable, long delay, TimeUnit unit) {
134return NeverScheduledFuture.create();
135}
136
137@Override
138public ListenableScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
139return NeverScheduledFuture.create();
140}
141
142@Override
143public ListenableScheduledFuture<?> scheduleAtFixedRate(
144Runnable command, long initialDelay, long period, TimeUnit unit) {
145return NeverScheduledFuture.create();
146}
147
148@Override
149public ListenableScheduledFuture<?> scheduleWithFixedDelay(
150Runnable command, long initialDelay, long delay, TimeUnit unit) {
151return NeverScheduledFuture.create();
152}
153
154private static class NeverScheduledFuture<V> extends AbstractFuture<V>
155implements ListenableScheduledFuture<V> {
156
157static <V> NeverScheduledFuture<V> create() {
158return new NeverScheduledFuture<>();
159}
160
161@Override
162public long getDelay(TimeUnit unit) {
163return Long.MAX_VALUE;
164}
165
166@Override
167public int compareTo(Delayed other) {
168return Long.compare(getDelay(NANOSECONDS), other.getDelay(NANOSECONDS));
169}
170}
171}
172}
173