Author: peter_firmstone Date: Fri Nov 27 05:26:15 2015 New Revision: 1716791
URL: http://svn.apache.org/viewvc?rev=1716791&view=rev Log: Fix Regression of Sun Bug 4404702. Additional Changes: Give jvm hint to minimize thread stack size (228k is minimum for 64 bit platforms) to increase scalability. Increase number of waiting idle threads by 1. Change position of Thread name change to avoid unnecessary changes. Modified: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/NewThreadAction.java river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/ThreadPool.java Modified: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/NewThreadAction.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/NewThreadAction.java?rev=1716791&r1=1716790&r2=1716791&view=diff ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/NewThreadAction.java (original) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/NewThreadAction.java Fri Nov 27 05:26:15 2015 @@ -78,14 +78,22 @@ public final class NewThreadAction imple private final Runnable runnable; private final String name; private final boolean daemon; + private final int stackSize; NewThreadAction(ThreadGroup group, Runnable runnable, String name, boolean daemon) { + this(group, runnable, name, daemon, 0); + } + + NewThreadAction(ThreadGroup group, Runnable runnable, + String name, boolean daemon, int stackSize) + { this.group = group; this.runnable = runnable; this.name = name; this.daemon = daemon; + this.stackSize = stackSize; } /** @@ -129,7 +137,7 @@ public final class NewThreadAction imple if (sm != null) { sm.checkPermission(getClassLoaderPermission); } - Thread t = new Thread(group, runnable, NAME_PREFIX + name); + Thread t = new Thread(group, runnable, NAME_PREFIX + name, stackSize); t.setContextClassLoader(ClassLoader.getSystemClassLoader()); t.setDaemon(daemon); return t; Modified: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/ThreadPool.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/ThreadPool.java?rev=1716791&r1=1716790&r2=1716791&view=diff ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/ThreadPool.java (original) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/thread/ThreadPool.java Fri Nov 27 05:26:15 2015 @@ -21,8 +21,8 @@ package org.apache.river.thread; import org.apache.river.action.GetLongAction; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -64,7 +64,7 @@ import java.util.logging.Logger; final class ThreadPool implements Executor, java.util.concurrent.Executor { /** how long a thread waits in the idle state before passing away */ - private static final long idleTimeout = // default 5 minutes + private static final long IDLE_TIMEOUT = // default 5 minutes ((Long) AccessController.doPrivileged(new GetLongAction( "org.apache.river.thread.idleThreadTimeout", 300000))) .longValue(); @@ -131,7 +131,7 @@ final class ThreadPool implements Execut */ ThreadPool(final ThreadGroup threadGroup, int delayFactor) { this.threadGroup = threadGroup; - queue = new LinkedBlockingQueue<Runnable>(); + queue = new ArrayBlockingQueue<Runnable>(32); workerCount = new AtomicInteger(); availableThreads = new AtomicInteger(); // Thread not started until after constructor completes @@ -140,28 +140,40 @@ final class ThreadPool implements Execut @Override public Object run() { - Runtime.getRuntime().addShutdownHook(new Thread ("ThreadPool destroy"){ - @Override - public void run (){ - try { - // Allow four seconds prior to shutdown for other - // processes to complete. - Thread.sleep(4000L); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - shutdown = true; - Thread [] threads = new Thread [workerCount.get() + 1 ]; - int count = threadGroup.enumerate(threads); - for (int i = 0; i < count; i++){ - threads [i].interrupt(); - } - } - }); + Runtime.getRuntime().addShutdownHook(shutdownHook()); return null; } }); } + + private Thread shutdownHook(){ + Thread t = new Thread ( new Runnable(){ + @Override + public void run (){ + try { + // Allow four seconds prior to shutdown for other + // processes to complete. + Thread.sleep(4000L); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + shutdown = true; + Thread [] threads = new Thread [workerCount.get() + 1 ]; + int count = threadGroup.enumerate(threads); + for (int i = 0; i < count; i++){ + threads [i].interrupt(); + } + } + },"ThreadPool destroy"); + /** + * See jtreg sun bug ID:4404702 + * This ensures that this thread doesn't unnecessarily hold + * a strong reference to a ClassLoader, thus preventing + * it from being garbage collected. + */ + t.setContextClassLoader(ClassLoader.getSystemClassLoader()); + return t; + } // This method must not block - Executor @Override @@ -173,15 +185,15 @@ final class ThreadPool implements Execut * threads available. * * Tasks must not be allowed to build up in the queue, in case - * of dependencies. + * of dependencies. */ - if ( availableThreads.get() < 1 ) { // need more threads. - if (shutdown) { - throw new RejectedExecutionException("ThreadPool shutdown"); - } - Thread t = AccessController.doPrivileged( - new NewThreadAction(threadGroup, new Worker(task), name, false)); - t.start(); + if ( availableThreads.get() < 2 )// Keep at least one thread ready. + { // need more threads. + if (shutdown) throw + new RejectedExecutionException("ThreadPool shutdown"); + Thread t = AccessController.doPrivileged( + new NewThreadAction(threadGroup, new Worker(task), name, false, 228)); + t.start(); } else { try { queue.put(task); @@ -268,17 +280,17 @@ final class ThreadPool implements Execut task = null; availableThreads.incrementAndGet(); try { - task = queue.poll(idleTimeout, TimeUnit.MILLISECONDS); + task = queue.poll(IDLE_TIMEOUT, TimeUnit.MILLISECONDS); } finally { availableThreads.decrementAndGet(); } - thread.setName(NewThreadAction.NAME_PREFIX + task); if (task != null) { + thread.setName(NewThreadAction.NAME_PREFIX + task); task.run(); + thread.setName(NewThreadAction.NAME_PREFIX + "Idle"); } else { break; //Timeout or spurious wakeup. - } - thread.setName(NewThreadAction.NAME_PREFIX + "Idle"); + } } catch (InterruptedException e){ thread.interrupt(); break;
