All Downloads are FREE. Search and download functionalities are using the official Maven repository.

alex.mojaki.s3upload.ExecutorServiceResultsHandler Maven / Gradle / Ivy

Go to download

Manages streaming of data to S3 without knowing the size beforehand and without keeping it all in memory or writing to disk.

There is a newer version: 2.2.4
Show newest version
package alex.mojaki.s3upload;

import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Wrapper around an ExecutorService that allows you to easily submit {@link Callable}s, get results via iteration,
 * and handle failure quickly. When a submitted callable throws an exception in its thread this
 * will result in a {@code RuntimeException} when iterating over results. Typical usage is as follows:
 * 

*

    *
  1. Create an ExecutorService and pass it to the constructor.
  2. *
  3. Create Callables and ensure that they respond to interruption, e.g. regularly call:
    {@code
     *     if (Thread.currentThread().isInterrupted()) {
     *         throw new RuntimeException("The thread was interrupted, likely indicating failure in a sibling thread.");
     *     }}
  4. *
  5. Pass the callables to the {@code submit()} method.
  6. *
  7. Call {@code finishedSubmitting()}.
  8. *
  9. Iterate over this object (e.g. with a foreach loop) to get results from the callables. * Each iteration will block waiting for the next result. * If one of the callables throws an unhandled exception or the thread is interrupted during iteration * then {@link ExecutorService#shutdownNow()} will be called resulting in all still running callables being interrupted, * and a {@code RuntimeException} will be thrown
  10. *
*

* You can also call {@code abort()} to shut down the threads yourself. */ public class ExecutorServiceResultsHandler implements Iterable { private ExecutorCompletionService completionService; private ExecutorService executorService; private AtomicInteger taskCount = new AtomicInteger(0); public ExecutorServiceResultsHandler(ExecutorService executorService) { this.executorService = executorService; completionService = new ExecutorCompletionService(executorService); } public void submit(Callable task) { completionService.submit(task); taskCount.incrementAndGet(); } public void finishedSubmitting() { executorService.shutdown(); } @Override public Iterator iterator() { return new Iterator() { @Override public boolean hasNext() { return taskCount.getAndDecrement() > 0; } @Override public V next() { Exception exception; try { return completionService.take().get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); exception = e; } catch (ExecutionException e) { exception = e; } abort(); throw new RuntimeException(exception); } @Override public void remove() { throw new UnsupportedOperationException("remove"); } }; } public void abort() { if (executorService != null) { executorService.shutdownNow(); } executorService = null; completionService = null; } /** * Convenience method to wait for the callables to finish for when you don't care about the results. */ public void awaitCompletion() { //noinspection StatementWithEmptyBody for (V ignored : this) { // do nothing } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy