Как получить список мертвых нитей из группы ThreadGroup? level 28

Ну собственно в названии и сам вопрос. Кто разобрался, подскажите. Нашел такой вариант, но он мне уж совсем не нравится и не работает)
public static void main(String[] args) {
        /*
 * For testing purposes */


        ThreadGroup tg = new ThreadGroup( "MyThreadGroup" );
        Thread subThread = new Thread( tg, "New Thread - Inactive" );
        try
        {
/*
* GETTING THREADS - PROBABLY BETTER TO GET IT BY USING
* getDeclaredFields() AND LOOPING TILL GET ONE OF TYPE
* Thread[] SINCE A FUTURE VERSION MIGHT CHANGE THE NAME
* BUT SINCE IS PACKAGE-LEVEL ACCESS, IT'S PROBABLY USED
* ELSEWHERE IN THE PACKAGE, AND THIS IS JUST AN EXAMPLE
*/
            Field field = tg.getClass().getDeclaredField( "threads" );

                //NEED TO SUPPRESS ACCESS CHECKS
            field.setAccessible( true ); //EVEN IF SECURITY IS OFF YOU NEED THIS!!!!

            Thread[] tgThreads = ( Thread[] ) field.get( tg );

            for ( int i = 0; i < tgThreads.length; i++ )
            {
                if ( tgThreads[ i ] != null )
                    System.out.println( tgThreads[ i ].getName() + " = " + tgThreads[ i ].isAlive() );
            }
        }
        catch (NoSuchFieldException nsfe)
        {
            nsfe.printStackTrace();
        }
        catch (IllegalAccessException iae)
        {
            iae.printStackTrace();
        }
    }

Получается строчка
Thread[] tgThreads = ( Thread[] ) field.get( tg );

не генерит мне массив. почитал, вроде можно как то залезть в System.SecurityManager и поставить ReflectPermission(«suppressAccessChecks»). но подход уж слишком хардкод. добираться до приватных полей через рефлексию…

9 комментариев

leshak
Dead_MOPO3
та читал я это. но там в методе, который должен, якобы, вернуть список всех тредов, он возвращает только живые
xprox4
Кто-нибудь нашел более-менее приемлемый способ получить список всех мертвых тредов?
TtTt
Не проверял, но есть теория.
Для того чтобы получить мертвые нити нужно: Список всех нитей — Список всех живых нитей = Список мертвых нитей.
Список всех нитей.
Создать поток демон, который будет заполнять общий список все нитей по принципу я тебя не знаю — давай к нам
Живые нити
Thread[] temp = new Thread[thG.activeCount()];
thG.enumerate(temp);

Где thG это объект ThreadGroup
Если у кого хватит опыта реализовать, то большое спасибо.
Yurets_Y
  • Yurets_Y
  • 0
  • Комментарий отредактирован 2016-06-10 16:05:37 пользователем Yurets_Y
Код проверял, все работает, через рефлекцию методом .getClass().getDeclaredField(«threads»); возвращает массив Thread[] threads, хранящий ссылки на все потоки, вот только обработанные потоки имеют ссылку null, а из null как говорят и взятки гладки, ни имени, ни свойств. Как вариант можно при запуске потоков дописать код, который будет сохранять все ссылки на потоки. а потом удалив из массива всех потоков, активные потоки получить список мертвых, но такую конструкцию можно соорудить только если ты автор всего кода, а не просто пытаешься в готовом коде выполнить счет активных и неактивных потоков группы. Для живых потоков метод работает, для мертвых нет.
Adeptius
  • Adeptius
  • 0
  • Комментарий отредактирован 2016-07-04 16:34:50 пользователем Adeptius
del
apache888
Getting a list of all threads in a specific state
The getState( ) method on Thread tells you if the thread is runnable or if it is blocked waiting on something. There are six states, defined by the Thread.State enum:

NEW. The thread has been created, but hasn't run yet.
TERMINATED. The thread has run to completion, but hasn't been deleted yet by the JVM.
RUNNABLE. The thread is running.
BLOCKED. The thread is blocked waiting on a lock (such as in a synchronized block or method).
WAITING. The thread is waiting until another thread calls notify( ).
TIMED_WAITING. The thread is either waiting or in a sleep( ).
During debugging it can be useful to monitor which threads are in which states. To get a list of threads in a specific state, get a list of all threads and extract the ones in the state you want.
Thread[] getAllThreads( final Thread.State state ) {
    final Thread[] allThreads = getAllThreads( );
    final Thread[] found = new Thread[allThreads.length];
    int nFound = 0;
    for ( Thread thread : allThreads )
        if ( thread.getState( ) == state )
            found[nFound++] = thread; 
    return java.util.Arrays.copyOf( found, nFound );
}
vampirit
  • vampirit
  • 0
  • Комментарий отредактирован 2017-03-14 04:20:42 пользователем vampirit
Думал, думал, вот, что надумал:

Это невозможно. Получив доступ к полю threads класса ThreadGroup мы получаем null на все завершенные нити. Значит группа удаляет все ссылки на завершенные нити, значит найти их после этого (не имея больше никаких ссылок не представляю как).

Что я понял:
1. Ссылка на нить удаляется из группы после выполнения
2. У нити удаляется ссылка на группу, после того как нить завершиться.
— все это происходить только на последней стадии (TERMINATED)

Учитывая эти 2 критичных момента, можно понять, что не подготовившись заранее нельзя получить список завершенных нитей, группа о них уже не помнит, как и они о ней.

Другой вариант, это когда мы заранее знаем, что нам надо иметь список нитей. Тогда при создании объекта, заносим его ссылку в лист. Можно в конструкторе нити, а если нить анонимная, то в run. Ну либо Завести лист про который нити не знают и ручками после создания нити добавлять, главное сохранить ссылку на нить.

package test;

import java.util.*;

public class ThreadGroupsTut {

    private final static Map <Thread, Thread.State> threadMap = new HashMap<>();


    public static void main(String[] args) throws InterruptedException {
        ThreadGroup group = new ThreadGroup("My");
        ThreadTerminated terminated = new ThreadTerminated(group, "Terminated ");
        ThreadAlive alive = new ThreadAlive(group, "Alive");


        Thread deamon = new Thread(){

            @Override
            public void run() {
                while (true){
                    for (Map.Entry<Thread,State> t : threadMap.entrySet()) {
                        Thread thread = t.getKey();
                        if (thread.getState() != t.getValue()){
                            System.out.println(String.format("%s : %s : %s",
                                    thread.getThreadGroup(), thread.getName(), thread.getState()));
                            t.setValue(thread.getState());
                        }
                    }
                }
            }
        };
        deamon.setDaemon(true);
        deamon.start();
        Thread.sleep(500);
        terminated.start();
        alive.start();

        Thread.sleep(5000);
        group.interrupt();

        Thread.sleep(1000);
        System.out.println(group.activeCount());
    }
    
    

    public static class ThreadTerminated extends Thread{
        public ThreadTerminated(ThreadGroup group, String name) {
            super(group, name);
            threadMap.put(this, null);
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class ThreadAlive extends Thread{

        public ThreadAlive(ThreadGroup group, String name) {
            super(group, name);
            threadMap.put(this, null);
        }

        @Override
        public void run() {
            while(!this.isInterrupted()){
            }
        }
    }
}
FogZ
  • FogZ
  • 0
  • Комментарий отредактирован 2018-03-31 18:36:24 пользователем FogZ
Я бы добавил, что поле threads остается null, пока не будет запущена хотя бы одна нить, в конструкторе которой указана ссылка на группу. То есть объект группы узнает о нити, только когда она запускается (в этот момент она видимо сообщает ему об этом).
(Мы можем создать кучу нитей и указать в них ссылку на группу, но не запускать их, и группа ничего про них знать не будет).

После запуска хотя бы 1 нити, threads начинает ссылаться на массив, причем там минимум 4 элемента. Если нить 1, то 3 остальных элемента null.

Далее, если количество запущенных нитей, приписанных к данной группе растет и не помещается в массив (по умолчанию из 4 элементов), то размер массива удваивается (4 — 8 — 16 — 32 -… элементов).

После завершения работы нити ссылка в массиве на эту нить удаляется, размер массива остается прежним.

Из всего вышесказанного можно сделать вывод, что мы можем разве что оценить количество мертвых нитей, узнав размер массива threads и количество живых нитей (метод enumerate). Но нужно учитывать, что ссылки на новые живые нити будут добавляться в массив вместо старых null.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.