--- a/jdk/src/share/classes/javax/management/monitor/Monitor.java Fri Mar 06 12:40:38 2009 +0300
+++ b/jdk/src/share/classes/javax/management/monitor/Monitor.java Mon Mar 09 22:49:21 2009 +0100
@@ -33,8 +33,9 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
@@ -174,14 +175,20 @@
new DaemonThreadFactory("Scheduler"));
/**
+ * Map containing the thread pool executor per thread group.
+ */
+ private static final Map<ThreadPoolExecutor, Void> executors =
+ new WeakHashMap<ThreadPoolExecutor, Void>();
+
+ /**
+ * Lock for executors map.
+ */
+ private static final Object executorsLock = new Object();
+
+ /**
* Maximum Pool Size
*/
private static final int maximumPoolSize;
-
- /**
- * Executor Service.
- */
- private static final ExecutorService executor;
static {
final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
final String maximumPoolSizeStr = AccessController.doPrivileged(
@@ -211,22 +218,9 @@
maximumPoolSize = maximumPoolSizeTmp;
}
}
- executor = new ThreadPoolExecutor(
- maximumPoolSize,
- maximumPoolSize,
- 60L,
- TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>(),
- new DaemonThreadFactory("Executor"));
- ((ThreadPoolExecutor)executor).allowCoreThreadTimeOut(true);
}
/**
- * Monitor task to be executed by the Executor Service.
- */
- private final MonitorTask monitorTask = new MonitorTask();
-
- /**
* Future associated to the current monitor task.
*/
private Future<?> monitorFuture;
@@ -234,7 +228,7 @@
/**
* Scheduler task to be executed by the Scheduler Service.
*/
- private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);
+ private final SchedulerTask schedulerTask = new SchedulerTask();
/**
* ScheduledFuture associated to the current scheduler task.
@@ -720,6 +714,7 @@
// Start the scheduler.
//
cleanupFutures();
+ schedulerTask.setMonitorTask(new MonitorTask());
schedulerFuture = scheduler.schedule(schedulerTask,
getGranularityPeriod(),
TimeUnit.MILLISECONDS);
@@ -1468,7 +1463,7 @@
*/
private class SchedulerTask implements Runnable {
- private Runnable task = null;
+ private MonitorTask task;
/*
* ------------------------------------------
@@ -1476,7 +1471,16 @@
* ------------------------------------------
*/
- public SchedulerTask(Runnable task) {
+ public SchedulerTask() {
+ }
+
+ /*
+ * ------------------------------------------
+ * GETTERS/SETTERS
+ * ------------------------------------------
+ */
+
+ public void setMonitorTask(MonitorTask task) {
this.task = task;
}
@@ -1488,7 +1492,7 @@
public void run() {
synchronized (Monitor.this) {
- Monitor.this.monitorFuture = executor.submit(task);
+ Monitor.this.monitorFuture = task.submit();
}
}
}
@@ -1501,6 +1505,8 @@
*/
private class MonitorTask implements Runnable {
+ private ThreadPoolExecutor executor;
+
/*
* ------------------------------------------
* CONSTRUCTORS
@@ -1508,6 +1514,38 @@
*/
public MonitorTask() {
+ // Find out if there's already an existing executor for the calling
+ // thread and reuse it. Otherwise, create a new one and store it in
+ // the executors map. If there is a SecurityManager, the group of
+ // System.getSecurityManager() is used, else the group of the thread
+ // instantiating this MonitorTask, i.e. the group of the thread that
+ // calls "Monitor.start()".
+ SecurityManager s = System.getSecurityManager();
+ ThreadGroup group = (s != null) ? s.getThreadGroup() :
+ Thread.currentThread().getThreadGroup();
+ synchronized (executorsLock) {
+ for (ThreadPoolExecutor e : executors.keySet()) {
+ DaemonThreadFactory tf =
+ (DaemonThreadFactory) e.getThreadFactory();
+ ThreadGroup tg = tf.getThreadGroup();
+ if (tg == group) {
+ executor = e;
+ break;
+ }
+ }
+ if (executor == null) {
+ executor = new ThreadPoolExecutor(
+ maximumPoolSize,
+ maximumPoolSize,
+ 60L,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ new DaemonThreadFactory("ThreadGroup<" +
+ group.getName() + "> Executor", group));
+ executor.allowCoreThreadTimeOut(true);
+ executors.put(executor, null);
+ }
+ }
}
/*
@@ -1516,6 +1554,10 @@
* ------------------------------------------
*/
+ public Future<?> submit() {
+ return executor.submit(this);
+ }
+
public void run() {
final ScheduledFuture<?> sf;
synchronized (Monitor.this) {
@@ -1574,6 +1616,15 @@
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
}
+ public DaemonThreadFactory(String poolName, ThreadGroup threadGroup) {
+ group = threadGroup;
+ namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
+ }
+
+ public ThreadGroup getThreadGroup() {
+ return group;
+ }
+
public Thread newThread(Runnable r) {
Thread t = new Thread(group,
r,