JavaのThreadGroupを試してみる
EffectiveJavaの「項目73 スレッドグループを避ける」にあるようにThreadGroupを自前で実装することは少なそうです。しかしその概念を知っておくのは有用と思われるので試してみました。
スレッドは管理とセキュリティのためにスレッドグループ(Thread Group)にまとめられます。スレッドグループは、他のスレッドグループに含めることができて、トップレベル、すなわち、システムスレッドグループを基点とした階層構造を提供します。
デフォルトのスレッドグループ
スレッドグループ名を明示的に指定しない場合、JVMがデフォルトのグループであるmainを割り当てます。
public static void main(String[] args) { System.out.printf("[%s] :%s\n", Thread.currentThread().getName(), Thread.currentThread().getThreadGroup()); }
結果
スレッドグループ名がmainでMaxPriorityが10であることが分かります。
[main] :java.lang.ThreadGroup[name=main,maxpri=10]
スレッドグループを作る
スレッドグループ内でactiveなスレッド数を数えてみます。ただし activeCount()
は推定値です。
現在のスレッドのスレッド・グループとそのサブグループに含まれるアクティブ・スレッドの推定数を返します。現在のスレッドのスレッド・グループ内のすべてのサブグループに対して再帰的な反復処理を行います。
public class Sample { public static void main(String[] args) { ThreadGroup myThreadGroup = new ThreadGroup("myThreadGroup"); for (int i = 0; i < 10; i++) { Thread thread = new Thread(myThreadGroup, new MyThread()::threadSleep); thread.start(); } while (myThreadGroup.activeCount() > 0) { try { System.out.printf("[%s] :activeCount() = %s\n", Thread.currentThread().getName(), myThreadGroup.activeCount()); Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } System.out.printf("[%s] :%s\n", Thread.currentThread().getName(), "finish."); } static class MyThread { Random random = new Random(); void threadSleep() { try { System.out.printf("[%s] :%s\n", Thread.currentThread().getName(), "sleep."); Thread.sleep(1000 * (random.nextInt(10)+1)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
結果
[Thread-0] :sleep. [main] :activeCount() = 10 [Thread-9] :sleep. [Thread-8] :sleep. [Thread-7] :sleep. [Thread-6] :sleep. [Thread-5] :sleep. [Thread-4] :sleep. [Thread-2] :sleep. [Thread-3] :sleep. [Thread-1] :sleep. [main] :activeCount() = 10 [main] :activeCount() = 10 [main] :activeCount() = 8 [main] :activeCount() = 7 [main] :activeCount() = 5 [main] :activeCount() = 4 [main] :activeCount() = 3 [main] :activeCount() = 2 [main] :activeCount() = 2 [main] :finish.
まぁ自前でThreadGroupを実装することはなく、java.util.concurrent.ThreadPoolExecutor
を使うことが望ましいので、あまり深く考えることはしないことにしましょう。