Hi John,
Thanks for your comments.
John Keiser wrote:
> 1. setMaxPriority(): the JavaDoc seems to indicate you can set max priority
> as high as you want up to MAX_PRIORITY. Why does GCJ only make it smaller
> and not larger?
The JCL says that you can only use this method to lower the maximum priority
of a thread group, not raise it. This makes sense to me, because the purpose
of setMaxPriority() is to limit what a thread can do with setPriority(). If a
thread could raise its own maximum priority (ie using
currentThread.getThreadGroup().setMaxPriority()) then there wouldn't really be
much point!
> 2. activeCount(): It seems activeCount() should only count live threads,
> right? Why count all threads?
Because as far as I can tell, and despite what the JCL suggests, "active
thread" just means "any thread that is in the threadgroup", regardless of
whether that thread has been started yet. When a thread finishes, it will
automatically removes itself from its group and thus be consided inactive.
> 3. activeGroupCount(): Similar question here--though I can see how
> Classpath's is probably wrong as well, counting all threads instead of all
> active groups.
I've assumed that "Active ThreadGroup" means "any threadgroup that isn't
destroyed" because its simpler and consistent with the assumption above.
> 4. synchronized: I noticed a lot of synchronized keywords were removed from
> one to the other. Do y'all feel they were unnecessary for thread safety?
> (Seems like if anything should be threadsafe, it's ThreadGroup and Thread.)
Oops. Somehow I dropped some synchronized flags. Certainly they should be at
least synchronized to the extent specified in the JCL. I guess things like
destroy() should be synchronized wrt addThread(). Will fix.
I've attached a couple of test cases for your points 1,2,3 above. These tests
run identically on JDK1.1.8, JDK1.2.2, and libgcj on Linux.
regards
[ bryce ]
public class TG
{
public static void main(String args[])
{
ThreadGroup tg = new ThreadGroup("fooz");
System.out.println (tg.isDaemon()); // false
System.out.println (tg.isDestroyed()); // false
tg.setDaemon(true);
System.out.println (tg.isDaemon()); // true
System.out.println (tg.isDestroyed()); // false
tg = new ThreadGroup("jsaz");
tg.setMaxPriority(2);
System.out.println (tg.getMaxPriority()); // 2
tg.setMaxPriority(3);
System.out.println (tg.getMaxPriority()); // 2
ThreadGroup tg2 = new ThreadGroup(tg, "pfiz");
System.out.println (tg2.getMaxPriority()); // 2
tg = Thread.currentThread().getThreadGroup();
tg.list();
/*
java.lang.ThreadGroup[name=main,maxpri=10]
Thread[main,5,main]
java.lang.ThreadGroup[name=fooz,maxpri=10]
java.lang.ThreadGroup[name=jsaz,maxpri=2]
java.lang.ThreadGroup[name=pfiz,maxpri=2]
*/
}
}
public class TGCount implements Runnable
{
public static void main(String[] args) throws InterruptedException
{
new TGCount();
}
public void run() {}
public TGCount() throws InterruptedException
{
ThreadGroup tg = new ThreadGroup("foo");
System.out.println (tg.activeCount()); // 0
Thread t = new Thread(tg, this);
System.out.println (tg.activeCount()); // 1
System.out.println (t.isAlive()); // false
t.start();
Thread.sleep(100);
System.out.println (t.isAlive()); // false
System.out.println (tg.activeCount()); // 0
tg.destroy();
tg = new ThreadGroup("foo");
ThreadGroup tg2 = new ThreadGroup(tg, "bar");
System.out.println (tg.activeGroupCount()); // 1
tg2.destroy();
System.out.println (tg.activeGroupCount()); // 0
}
}