LINUX.ORG.RU

Java thread


0

0

Наивный вопрос по Жабке (нету под рукой проверить):

Я запускаю из одного треда (А) другой (Б), то есть делаю объект (О) класса thread и говорю ему из (А) start, что запускает в виде треда (Б) перекрытый run объекта (О). Надеюсь, я могу потом из (А) еще раз позвать start того же объекта (О), что создаст новый тред (В), исполняющий тот же код, что и (Б)? И стеки у них будут разные, но поля объекта(О), который их стартовал, будут видны и из (А),и из (Б), и из (В)?

Еще наивный вопрос: допустим, я сделал в стеке thread объект, стартанул его run startом, и управление из стека ушло. Как garbage collector отнесется к такому объекту? Как я понимаю, с уважением, поскольку, пока тред не сдох, из его стека существует ссылка типа ЦеППшного this (не знаю, как оно я Жабке зовется) на vmt. Но в исходном треде объект-папа уже ушел, и вся информация о дочке утеряна... Есть ли способ ее восстановить?

Проще говоря, можно ли добраться из треда (А) до всех тредов, которые он запустил, не обращаясь к методам соответствующих thread объектов?

★★★★★

> я сделал в стеке thread объект

Все объекты в жабе динамические, если говорить терминами Паскаля/Дельфи, то есть создаются в аналоге "кучи" (heap). То что ты называешь "стековым объектом", на самом деле лишь ссылка на нормальный динамический объект в "куче".

> Как garbage collector отнесется к такому объекту?

Никак. Пока тред выполняется, сборщик мусора не трогает его и те объекты, на которые он ссылается.

> Я запускаю из одного треда (А) другой (Б), то есть делаю объект (О) класса thread и говорю ему из (А) start, что запускает в виде треда (Б) перекрытый run объекта (О). Надеюсь, я могу потом из (А) еще раз позвать start того же объекта (О)

А вот тут ты загнал :-) start() всего лишь активирует выполнение треда. Если ты повторно позовешь "start() того же объекта", то если этот самый тред уже выполняется, то ничего не произойдет (либо придет exception что "тред уже выполняется").

То, что стеки раздельные, никакого значения не имеет - как я уже говорил, все объекты динамические и глобальные, живут в куче и могут быть адресованы из любого треда, в который не важно каким образом попала ссылка на соответствующий объект.

no-dashi ★★★★★
()

> Проще говоря, можно ли добраться из треда (А) до всех тредов

Легко. Заведи глобальный статичный Vector, в котором будут
регистрироваться все твои порожденные нити (в конструкторе)
переопределенного класса на основе Thread).

Внутри метода run() каждой нити, перед возвратом из run(),
просто удаляй из этого вектора ссылку на this:

public class Singleton {
    public static Vector allthreads;
}

class MyThread extends Thread {
     public MyThread() { super(); Singleton.allthreads.add( this ); }
     public void run() {
         ... делаешь что тебе надо...;
         Singleton.allthreads.remove( this );
     }
}

public class starter {
     public static void main(String args[]) {
         Sigleton.allthreads = new Vector();
         ... вперед и с песней ...
     }
}

Все свои треды порождай от MyThread, и тогда из любого места
можешь найти в Sigleton.allthreads любую из своих выполняющихся
нитей

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

Thanks,

>> я сделал в стеке thread объект

> Все объекты в жабе динамические,

Ну я неточно выразился: единственная ссылка на объект в стеке, и вот она из стека выходит -- все, больше ссылок нет.

> Пока тред выполняется, сборщик мусора не трогает его

То есть это просто явно прописано в стандарте?

> Если ты повторно позовешь "start() того же объекта", то если этот самый тред уже выполняется, то ничего не произойдет (либо придет exception что "тред уже выполняется").

Гы! То есть, чтобы запустить пул одинаковых тредов, мне придется клонировать объекты? Не думал...

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от no-dashi

> Легко. Заведи глобальный статичный Vector,

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

Может, есть какой-то способ получить информацию о тредах, стартованных данным тредом? Понимаю, что ответ, скорее всего, "нет", но -- чем черт не шутит?

Die-Hard ★★★★★
() автор топика
Ответ на: комментарий от Die-Hard

> Может, есть какой-то способ получить информацию о тредах, стартованных данным тредом? Понимаю, что ответ, скорее всего, "нет", но -- чем черт не шутит?

Нет :)

Можно почитать на тему ThreadGroup вместо массива.

Legioner ★★★★★
()

> Еще наивный вопрос: допустим, я сделал в стеке thread объект, стартанул его run startом, и управление из стека ушло. Как garbage collector отнесется к такому объекту? Как я понимаю, с уважением, поскольку, пока тред не сдох, из его стека существует ссылка типа ЦеППшного this (не знаю, как оно я Жабке зовется) на vmt.

Для GC все треды процесса равнозначны, и корни считаются для всех. Т.к. в треде выполняется метод thread.run, естественно объект будет жить.

Legioner ★★★★★
()
Ответ на: комментарий от Die-Hard

> Гы! То есть, чтобы запустить пул одинаковых тредов, мне придется клонировать объекты?

Да, каждый объект ведь имеет средства для взаимодействия с тредом, interrupt и всё такое.

Legioner ★★★★★
()
Ответ на: комментарий от Die-Hard

> Проблема в том, что я это не сделал :( Теперь есть куча методов,
> из которых запускались треды, код которых лучше не трогать без
> крайней необходимости

В том-то и фишка, что переписывать там надо очень и очень немного,
в простейшем случае это выглядит так:

1. Создать класс ListedThread, производный от Thread,
экземпляры которого в своем конструкторе регистрируются
в списке нитей

2. Ввести в этот класс метод public void ext_run();

3. Перекрыть метод run() следующим образом

public void run() {
    try { ext_run(); } catch (Exception e) {};
    Singleton.allobjects.remove( self );
)

4. Перекрыть метод void interrupt(), написав в нем что-то такое:

public void interrupt() {
    Singleton.allobjects.remove( self );
    super.interrupt();
}

Это на случай, если кто-нибудь будет останавливать нити через
вызов interrupt(), чтобы не оставить "висящих" объектов.

5. В ваших классах, производных от Thread, просто заменить
родителя, то есть вместо class MyThread extends Thread
написать class MyThread extends ListedThread.

И все. То есть изменений там на час работы :-)

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

no-dashi:

> В том-то и фишка, что переписывать там надо очень и очень немного, ...

:-) Инкапсуляция рулит, я знаю! Ну, примерно так и сделали. Все работает, спасибо.

Die-Hard ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.