rt/emul/compact/src/main/java/java/util/concurrent/AbstractExecutorService.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 19 Mar 2016 10:46:31 +0100
branchjdk7-b147
changeset 1890 212417b74b72
permissions -rw-r--r--
Bringing in all concurrent package from JDK7-b147
jaroslav@1890
     1
/*
jaroslav@1890
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@1890
     3
 *
jaroslav@1890
     4
 * This code is free software; you can redistribute it and/or modify it
jaroslav@1890
     5
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@1890
     6
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@1890
     7
 * particular file as subject to the "Classpath" exception as provided
jaroslav@1890
     8
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@1890
     9
 *
jaroslav@1890
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@1890
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@1890
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@1890
    13
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@1890
    14
 * accompanied this code).
jaroslav@1890
    15
 *
jaroslav@1890
    16
 * You should have received a copy of the GNU General Public License version
jaroslav@1890
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@1890
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@1890
    19
 *
jaroslav@1890
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@1890
    21
 * or visit www.oracle.com if you need additional information or have any
jaroslav@1890
    22
 * questions.
jaroslav@1890
    23
 */
jaroslav@1890
    24
jaroslav@1890
    25
/*
jaroslav@1890
    26
 * This file is available under and governed by the GNU General Public
jaroslav@1890
    27
 * License version 2 only, as published by the Free Software Foundation.
jaroslav@1890
    28
 * However, the following notice accompanied the original version of this
jaroslav@1890
    29
 * file:
jaroslav@1890
    30
 *
jaroslav@1890
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
jaroslav@1890
    32
 * Expert Group and released to the public domain, as explained at
jaroslav@1890
    33
 * http://creativecommons.org/publicdomain/zero/1.0/
jaroslav@1890
    34
 */
jaroslav@1890
    35
jaroslav@1890
    36
package java.util.concurrent;
jaroslav@1890
    37
import java.util.*;
jaroslav@1890
    38
jaroslav@1890
    39
/**
jaroslav@1890
    40
 * Provides default implementations of {@link ExecutorService}
jaroslav@1890
    41
 * execution methods. This class implements the <tt>submit</tt>,
jaroslav@1890
    42
 * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
jaroslav@1890
    43
 * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
jaroslav@1890
    44
 * to the {@link FutureTask} class provided in this package.  For example,
jaroslav@1890
    45
 * the implementation of <tt>submit(Runnable)</tt> creates an
jaroslav@1890
    46
 * associated <tt>RunnableFuture</tt> that is executed and
jaroslav@1890
    47
 * returned. Subclasses may override the <tt>newTaskFor</tt> methods
jaroslav@1890
    48
 * to return <tt>RunnableFuture</tt> implementations other than
jaroslav@1890
    49
 * <tt>FutureTask</tt>.
jaroslav@1890
    50
 *
jaroslav@1890
    51
 * <p> <b>Extension example</b>. Here is a sketch of a class
jaroslav@1890
    52
 * that customizes {@link ThreadPoolExecutor} to use
jaroslav@1890
    53
 * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
jaroslav@1890
    54
 *  <pre> {@code
jaroslav@1890
    55
 * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
jaroslav@1890
    56
 *
jaroslav@1890
    57
 *   static class CustomTask<V> implements RunnableFuture<V> {...}
jaroslav@1890
    58
 *
jaroslav@1890
    59
 *   protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
jaroslav@1890
    60
 *       return new CustomTask<V>(c);
jaroslav@1890
    61
 *   }
jaroslav@1890
    62
 *   protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
jaroslav@1890
    63
 *       return new CustomTask<V>(r, v);
jaroslav@1890
    64
 *   }
jaroslav@1890
    65
 *   // ... add constructors, etc.
jaroslav@1890
    66
 * }}</pre>
jaroslav@1890
    67
 *
jaroslav@1890
    68
 * @since 1.5
jaroslav@1890
    69
 * @author Doug Lea
jaroslav@1890
    70
 */
jaroslav@1890
    71
public abstract class AbstractExecutorService implements ExecutorService {
jaroslav@1890
    72
jaroslav@1890
    73
    /**
jaroslav@1890
    74
     * Returns a <tt>RunnableFuture</tt> for the given runnable and default
jaroslav@1890
    75
     * value.
jaroslav@1890
    76
     *
jaroslav@1890
    77
     * @param runnable the runnable task being wrapped
jaroslav@1890
    78
     * @param value the default value for the returned future
jaroslav@1890
    79
     * @return a <tt>RunnableFuture</tt> which when run will run the
jaroslav@1890
    80
     * underlying runnable and which, as a <tt>Future</tt>, will yield
jaroslav@1890
    81
     * the given value as its result and provide for cancellation of
jaroslav@1890
    82
     * the underlying task.
jaroslav@1890
    83
     * @since 1.6
jaroslav@1890
    84
     */
jaroslav@1890
    85
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
jaroslav@1890
    86
        return new FutureTask<T>(runnable, value);
jaroslav@1890
    87
    }
jaroslav@1890
    88
jaroslav@1890
    89
    /**
jaroslav@1890
    90
     * Returns a <tt>RunnableFuture</tt> for the given callable task.
jaroslav@1890
    91
     *
jaroslav@1890
    92
     * @param callable the callable task being wrapped
jaroslav@1890
    93
     * @return a <tt>RunnableFuture</tt> which when run will call the
jaroslav@1890
    94
     * underlying callable and which, as a <tt>Future</tt>, will yield
jaroslav@1890
    95
     * the callable's result as its result and provide for
jaroslav@1890
    96
     * cancellation of the underlying task.
jaroslav@1890
    97
     * @since 1.6
jaroslav@1890
    98
     */
jaroslav@1890
    99
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
jaroslav@1890
   100
        return new FutureTask<T>(callable);
jaroslav@1890
   101
    }
jaroslav@1890
   102
jaroslav@1890
   103
    /**
jaroslav@1890
   104
     * @throws RejectedExecutionException {@inheritDoc}
jaroslav@1890
   105
     * @throws NullPointerException       {@inheritDoc}
jaroslav@1890
   106
     */
jaroslav@1890
   107
    public Future<?> submit(Runnable task) {
jaroslav@1890
   108
        if (task == null) throw new NullPointerException();
jaroslav@1890
   109
        RunnableFuture<Void> ftask = newTaskFor(task, null);
jaroslav@1890
   110
        execute(ftask);
jaroslav@1890
   111
        return ftask;
jaroslav@1890
   112
    }
jaroslav@1890
   113
jaroslav@1890
   114
    /**
jaroslav@1890
   115
     * @throws RejectedExecutionException {@inheritDoc}
jaroslav@1890
   116
     * @throws NullPointerException       {@inheritDoc}
jaroslav@1890
   117
     */
jaroslav@1890
   118
    public <T> Future<T> submit(Runnable task, T result) {
jaroslav@1890
   119
        if (task == null) throw new NullPointerException();
jaroslav@1890
   120
        RunnableFuture<T> ftask = newTaskFor(task, result);
jaroslav@1890
   121
        execute(ftask);
jaroslav@1890
   122
        return ftask;
jaroslav@1890
   123
    }
jaroslav@1890
   124
jaroslav@1890
   125
    /**
jaroslav@1890
   126
     * @throws RejectedExecutionException {@inheritDoc}
jaroslav@1890
   127
     * @throws NullPointerException       {@inheritDoc}
jaroslav@1890
   128
     */
jaroslav@1890
   129
    public <T> Future<T> submit(Callable<T> task) {
jaroslav@1890
   130
        if (task == null) throw new NullPointerException();
jaroslav@1890
   131
        RunnableFuture<T> ftask = newTaskFor(task);
jaroslav@1890
   132
        execute(ftask);
jaroslav@1890
   133
        return ftask;
jaroslav@1890
   134
    }
jaroslav@1890
   135
jaroslav@1890
   136
    /**
jaroslav@1890
   137
     * the main mechanics of invokeAny.
jaroslav@1890
   138
     */
jaroslav@1890
   139
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
jaroslav@1890
   140
                            boolean timed, long nanos)
jaroslav@1890
   141
        throws InterruptedException, ExecutionException, TimeoutException {
jaroslav@1890
   142
        if (tasks == null)
jaroslav@1890
   143
            throw new NullPointerException();
jaroslav@1890
   144
        int ntasks = tasks.size();
jaroslav@1890
   145
        if (ntasks == 0)
jaroslav@1890
   146
            throw new IllegalArgumentException();
jaroslav@1890
   147
        List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
jaroslav@1890
   148
        ExecutorCompletionService<T> ecs =
jaroslav@1890
   149
            new ExecutorCompletionService<T>(this);
jaroslav@1890
   150
jaroslav@1890
   151
        // For efficiency, especially in executors with limited
jaroslav@1890
   152
        // parallelism, check to see if previously submitted tasks are
jaroslav@1890
   153
        // done before submitting more of them. This interleaving
jaroslav@1890
   154
        // plus the exception mechanics account for messiness of main
jaroslav@1890
   155
        // loop.
jaroslav@1890
   156
jaroslav@1890
   157
        try {
jaroslav@1890
   158
            // Record exceptions so that if we fail to obtain any
jaroslav@1890
   159
            // result, we can throw the last exception we got.
jaroslav@1890
   160
            ExecutionException ee = null;
jaroslav@1890
   161
            long lastTime = timed ? System.nanoTime() : 0;
jaroslav@1890
   162
            Iterator<? extends Callable<T>> it = tasks.iterator();
jaroslav@1890
   163
jaroslav@1890
   164
            // Start one task for sure; the rest incrementally
jaroslav@1890
   165
            futures.add(ecs.submit(it.next()));
jaroslav@1890
   166
            --ntasks;
jaroslav@1890
   167
            int active = 1;
jaroslav@1890
   168
jaroslav@1890
   169
            for (;;) {
jaroslav@1890
   170
                Future<T> f = ecs.poll();
jaroslav@1890
   171
                if (f == null) {
jaroslav@1890
   172
                    if (ntasks > 0) {
jaroslav@1890
   173
                        --ntasks;
jaroslav@1890
   174
                        futures.add(ecs.submit(it.next()));
jaroslav@1890
   175
                        ++active;
jaroslav@1890
   176
                    }
jaroslav@1890
   177
                    else if (active == 0)
jaroslav@1890
   178
                        break;
jaroslav@1890
   179
                    else if (timed) {
jaroslav@1890
   180
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
jaroslav@1890
   181
                        if (f == null)
jaroslav@1890
   182
                            throw new TimeoutException();
jaroslav@1890
   183
                        long now = System.nanoTime();
jaroslav@1890
   184
                        nanos -= now - lastTime;
jaroslav@1890
   185
                        lastTime = now;
jaroslav@1890
   186
                    }
jaroslav@1890
   187
                    else
jaroslav@1890
   188
                        f = ecs.take();
jaroslav@1890
   189
                }
jaroslav@1890
   190
                if (f != null) {
jaroslav@1890
   191
                    --active;
jaroslav@1890
   192
                    try {
jaroslav@1890
   193
                        return f.get();
jaroslav@1890
   194
                    } catch (ExecutionException eex) {
jaroslav@1890
   195
                        ee = eex;
jaroslav@1890
   196
                    } catch (RuntimeException rex) {
jaroslav@1890
   197
                        ee = new ExecutionException(rex);
jaroslav@1890
   198
                    }
jaroslav@1890
   199
                }
jaroslav@1890
   200
            }
jaroslav@1890
   201
jaroslav@1890
   202
            if (ee == null)
jaroslav@1890
   203
                ee = new ExecutionException();
jaroslav@1890
   204
            throw ee;
jaroslav@1890
   205
jaroslav@1890
   206
        } finally {
jaroslav@1890
   207
            for (Future<T> f : futures)
jaroslav@1890
   208
                f.cancel(true);
jaroslav@1890
   209
        }
jaroslav@1890
   210
    }
jaroslav@1890
   211
jaroslav@1890
   212
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
jaroslav@1890
   213
        throws InterruptedException, ExecutionException {
jaroslav@1890
   214
        try {
jaroslav@1890
   215
            return doInvokeAny(tasks, false, 0);
jaroslav@1890
   216
        } catch (TimeoutException cannotHappen) {
jaroslav@1890
   217
            assert false;
jaroslav@1890
   218
            return null;
jaroslav@1890
   219
        }
jaroslav@1890
   220
    }
jaroslav@1890
   221
jaroslav@1890
   222
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
jaroslav@1890
   223
                           long timeout, TimeUnit unit)
jaroslav@1890
   224
        throws InterruptedException, ExecutionException, TimeoutException {
jaroslav@1890
   225
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
jaroslav@1890
   226
    }
jaroslav@1890
   227
jaroslav@1890
   228
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
jaroslav@1890
   229
        throws InterruptedException {
jaroslav@1890
   230
        if (tasks == null)
jaroslav@1890
   231
            throw new NullPointerException();
jaroslav@1890
   232
        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
jaroslav@1890
   233
        boolean done = false;
jaroslav@1890
   234
        try {
jaroslav@1890
   235
            for (Callable<T> t : tasks) {
jaroslav@1890
   236
                RunnableFuture<T> f = newTaskFor(t);
jaroslav@1890
   237
                futures.add(f);
jaroslav@1890
   238
                execute(f);
jaroslav@1890
   239
            }
jaroslav@1890
   240
            for (Future<T> f : futures) {
jaroslav@1890
   241
                if (!f.isDone()) {
jaroslav@1890
   242
                    try {
jaroslav@1890
   243
                        f.get();
jaroslav@1890
   244
                    } catch (CancellationException ignore) {
jaroslav@1890
   245
                    } catch (ExecutionException ignore) {
jaroslav@1890
   246
                    }
jaroslav@1890
   247
                }
jaroslav@1890
   248
            }
jaroslav@1890
   249
            done = true;
jaroslav@1890
   250
            return futures;
jaroslav@1890
   251
        } finally {
jaroslav@1890
   252
            if (!done)
jaroslav@1890
   253
                for (Future<T> f : futures)
jaroslav@1890
   254
                    f.cancel(true);
jaroslav@1890
   255
        }
jaroslav@1890
   256
    }
jaroslav@1890
   257
jaroslav@1890
   258
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
jaroslav@1890
   259
                                         long timeout, TimeUnit unit)
jaroslav@1890
   260
        throws InterruptedException {
jaroslav@1890
   261
        if (tasks == null || unit == null)
jaroslav@1890
   262
            throw new NullPointerException();
jaroslav@1890
   263
        long nanos = unit.toNanos(timeout);
jaroslav@1890
   264
        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
jaroslav@1890
   265
        boolean done = false;
jaroslav@1890
   266
        try {
jaroslav@1890
   267
            for (Callable<T> t : tasks)
jaroslav@1890
   268
                futures.add(newTaskFor(t));
jaroslav@1890
   269
jaroslav@1890
   270
            long lastTime = System.nanoTime();
jaroslav@1890
   271
jaroslav@1890
   272
            // Interleave time checks and calls to execute in case
jaroslav@1890
   273
            // executor doesn't have any/much parallelism.
jaroslav@1890
   274
            Iterator<Future<T>> it = futures.iterator();
jaroslav@1890
   275
            while (it.hasNext()) {
jaroslav@1890
   276
                execute((Runnable)(it.next()));
jaroslav@1890
   277
                long now = System.nanoTime();
jaroslav@1890
   278
                nanos -= now - lastTime;
jaroslav@1890
   279
                lastTime = now;
jaroslav@1890
   280
                if (nanos <= 0)
jaroslav@1890
   281
                    return futures;
jaroslav@1890
   282
            }
jaroslav@1890
   283
jaroslav@1890
   284
            for (Future<T> f : futures) {
jaroslav@1890
   285
                if (!f.isDone()) {
jaroslav@1890
   286
                    if (nanos <= 0)
jaroslav@1890
   287
                        return futures;
jaroslav@1890
   288
                    try {
jaroslav@1890
   289
                        f.get(nanos, TimeUnit.NANOSECONDS);
jaroslav@1890
   290
                    } catch (CancellationException ignore) {
jaroslav@1890
   291
                    } catch (ExecutionException ignore) {
jaroslav@1890
   292
                    } catch (TimeoutException toe) {
jaroslav@1890
   293
                        return futures;
jaroslav@1890
   294
                    }
jaroslav@1890
   295
                    long now = System.nanoTime();
jaroslav@1890
   296
                    nanos -= now - lastTime;
jaroslav@1890
   297
                    lastTime = now;
jaroslav@1890
   298
                }
jaroslav@1890
   299
            }
jaroslav@1890
   300
            done = true;
jaroslav@1890
   301
            return futures;
jaroslav@1890
   302
        } finally {
jaroslav@1890
   303
            if (!done)
jaroslav@1890
   304
                for (Future<T> f : futures)
jaroslav@1890
   305
                    f.cancel(true);
jaroslav@1890
   306
        }
jaroslav@1890
   307
    }
jaroslav@1890
   308
jaroslav@1890
   309
}