Restart.java revision 893:f06f30b29f36
1/* 2 * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24/* @test 25 * @bug 4607272 26 * @summary Unit test for AsynchronousChannelGroup 27 * @build Restart 28 * @run main/othervm -XX:-UseVMInterruptibleIO Restart 29 */ 30 31import java.nio.channels.*; 32import java.net.*; 33import java.util.*; 34import java.util.concurrent.*; 35import java.util.concurrent.atomic.*; 36import java.io.IOException; 37 38/** 39 * Exercise replacement of threads in the thread pool when completion handlers 40 * terminate due to errors or runtime exceptions. 41 */ 42 43public class Restart { 44 static final Random rand = new Random(); 45 46 public static void main(String[] args) throws Exception { 47 // thread group for thread pools 48 final ThreadGroup tg = new ThreadGroup("test"); 49 50 // keep track of the number of threads that terminate 51 final AtomicInteger exceptionCount = new AtomicInteger(0); 52 final Thread.UncaughtExceptionHandler ueh = 53 new Thread.UncaughtExceptionHandler() { 54 public void uncaughtException(Thread t, Throwable e) { 55 exceptionCount.incrementAndGet(); 56 } 57 }; 58 ThreadFactory factory = new ThreadFactory() { 59 @Override 60 public Thread newThread(Runnable r) { 61 Thread t = new Thread(tg, r); 62 t.setUncaughtExceptionHandler(ueh); 63 return t; 64 } 65 }; 66 67 // group with fixed thread pool 68 int nThreads = 1 + rand.nextInt(4); 69 AsynchronousChannelGroup group = 70 AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory); 71 testRestart(group, 100); 72 group.shutdown(); 73 74 // group with custom thread pool 75 ExecutorService pool = Executors.newCachedThreadPool(factory); 76 group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5)); 77 testRestart(group, 100); 78 group.shutdown(); 79 80 // give time for threads to terminate 81 Thread.sleep(3000); 82 int actual = exceptionCount.get(); 83 if (actual != 200) 84 throw new RuntimeException(actual + " exceptions, expected: " + 200); 85 } 86 87 static void testRestart(AsynchronousChannelGroup group, int count) 88 throws Exception 89 { 90 AsynchronousServerSocketChannel listener = 91 AsynchronousServerSocketChannel.open(group) 92 .bind(new InetSocketAddress(0)); 93 94 for (int i=0; i<count; i++) { 95 final CountDownLatch latch = new CountDownLatch(1); 96 97 listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() { 98 public void completed(AsynchronousSocketChannel ch, Void att) { 99 try { 100 ch.close(); 101 } catch (IOException ignore) { } 102 103 latch.countDown(); 104 105 // throw error or runtime exception 106 if (rand.nextBoolean()) { 107 throw new Error(); 108 } else { 109 throw new RuntimeException(); 110 } 111 } 112 public void failed(Throwable exc, Void att) { 113 } 114 public void cancelled(Void att) { 115 } 116 }); 117 118 // establish loopback connection which should cause completion 119 // handler to be invoked. 120 int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); 121 AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); 122 InetAddress lh = InetAddress.getLocalHost(); 123 ch.connect(new InetSocketAddress(lh, port)).get(); 124 ch.close(); 125 126 // wait for handler to be invoked 127 latch.await(); 128 } 129 130 // clean-up 131 listener.close(); 132 } 133} 134