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;


Reply via email to