code: // from gee.cs.oswego.edu/home/jsr166/jsr166
  
  package jsr166tests.jtreg.util.concurrent.FutureTask;
  
  /*
   * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  /*
   * @test
   * @bug 6431315
   * @summary ExecutorService.invokeAll might hang
   * @author Martin Buchholz
   */
  
  import java.util.*;
  import java.util.concurrent.*;
  
  /**
   * Adapted from Doug Lea, which was...
   * adapted from a posting by Tom Sugden tom at epcc.ed.ac.uk
   */
  public class BlockingTaskExecutor {
  
      static void realMain(String[] args) throws Throwable {
          for (int i = 1; i <= 100; i++) {
              System.out.print(".");
              test();
          }
      }
  
      static void test() throws Throwable {
          final ExecutorService executor = Executors.newCachedThreadPool();
  
          final NotificationReceiver notifiee1 = new NotificationReceiver();
          final NotificationReceiver notifiee2 = new NotificationReceiver();
  
          final Collection<Callable<Object>> tasks =
              new ArrayList<Callable<Object>>();
          tasks.add(new BlockingTask(notifiee1));
          tasks.add(new BlockingTask(notifiee2));
          tasks.add(new NonBlockingTask());
  
          // start a thread to invoke the tasks
          Thread thread = new Thread() { public void run() {
              try { executor.invokeAll(tasks); }
              catch (RejectedExecutionException t) {/* OK */}
              catch (Throwable t) { unexpected(t); }}};
          thread.start();
  
          // Wait until tasks begin execution
          notifiee1.waitForNotification();
          notifiee2.waitForNotification();
  
          // Now try to shutdown the executor service while tasks
          // are blocked.  This should cause the tasks to be
          // interrupted.
          executor.shutdownNow();
          if (! executor.awaitTermination(5, TimeUnit.SECONDS))
              throw new Error("Executor stuck");
  
          // Wait for the invocation thread to complete.
          thread.join(1000);
          if (thread.isAlive()) {
              thread.interrupt();
              thread.join(1000);
              throw new Error("invokeAll stuck");
          }
      }
  
      /**
       * A helper class with a method to wait for a notification.
       *
       * The notification is received via the
       * <code>sendNotification</code> method.
       */
      static class NotificationReceiver {
          /** Has the notifiee been notified? */
          boolean notified = false;
  
          /**
           * Notify the notification receiver.
           */
          public synchronized void sendNotification() {
              notified = true;
              notifyAll();
          }
  
          /**
           * Waits until a notification has been received.
           *
           * @throws InterruptedException if the wait is interrupted
           */
          public synchronized void waitForNotification()
              throws InterruptedException {
              while (! notified)
                  wait();
          }
      }
  
      /**
       * A callable task that blocks until it is interrupted.
       * This task sends a notification to a notification receiver when
       * it is first called.
       */
      static class BlockingTask implements Callable<Object> {
          private final NotificationReceiver notifiee;
  
          BlockingTask(NotificationReceiver notifiee) {
              this.notifiee = notifiee;
          }
  
          public Object call() throws InterruptedException {
              notifiee.sendNotification();
  
              // wait indefinitely until task is interrupted
              while (true) {
                  synchronized (this) {
                      wait();
                  }
              }
          }
      }
  
      /**
       * A callable task that simply returns a string result.
       */
      static class NonBlockingTask implements Callable<Object> {
          public Object call() {
              return "NonBlockingTaskResult";
          }
      }
  
      //--------------------- Infrastructure ---------------------------
      static volatile int passed = 0, failed = 0;
      static void pass() {passed++;}
      static void fail() {failed++; Thread.dumpStack();}
      static void fail(String msg) {System.out.println(msg); fail();}
      static void unexpected(Throwable t) {failed++; t.printStackTrace();}
      static void check(boolean cond) {if (cond) pass(); else fail();}
      static void equal(Object x, Object y) {
          if (x == null ? y == null : x.equals(y)) pass();
          else fail(x + " not equal to " + y);}
      public static void main(String[] args) throws Throwable {
          try {realMain(args);} catch (Throwable t) {unexpected(t);}
          System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
          if (failed > 0) throw new AssertionError("Some tests failed");}
  }
  