Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Опять потоки и синхронизация


Автор: Anton Vatchenko 21.12.2006, 15:35
У меня такая проблема. Есть главный поток, который плодит потоки (Main), есть поток, который "наблюдает" за созданными потоками, то есть всем им шлет сообщения (Update). В классе Main есть Вектор, в котором хранятся указатели на потоки. Создается новый поток - добавляется элемент в Вектор. Вот другой вопрос: как при выходе из потока не сломать Update. Приведу куски:

Код

public class Main {
    static Vector thread;

    void add() {
        [Создаем здесь поток типа MyThread и запускаем]
        thread.addElement(t);
    }
}

public class Update {
    public void run() {
        try {
            while (true) {
                    for (int i = 0; i < Main.thread.size(); i++) {
                       [Что-то делаем с потоками]
                    }
            }
        }
    }
}

class MyThread extends Thread {
    public void run() {
        while (true) {
            [Что-то делаем, но рано или поздно выходим]
        }
        for(int i = 0; i < Main.thread.size(); i++)
            if((MyThread)Main.thread.elementAt(i) == this) {
                Main.thread.removeElementAt(i);
                break;
            }
    }
}


Получается, что иногда в Update производится работа с уже удаленным из списка потоком, который уже не работает...

Автор: powerOn 21.12.2006, 16:44
Цитата(Anton Vatchenko @  21.12.2006,  15:35 Найти цитируемый пост)
производится работа с уже удаленным из списка потоком, который уже не работает...

попробуй прежде чем что-то с потоком делать, выполнить проверку: жив он или нет. У класса Thread есть подходящий метод: isAlive(). Если поток не живой, то путь его из коллекции удалит тот, кто и делал проверку. 

Автор: Anton Vatchenko 21.12.2006, 17:26
проверку то можно сделать, но работа с потоком может производиться около секунды. Не делать же перед каждой командой проверку, жив ли он еще...

Автор: Shurr 21.12.2006, 18:56
Не совсем понятен один момент: как работа самого потока MyThread совмещается с апдейтом этого потока, причем в течении секунды? Они работают с независимыми кусками данных, или что? Не совсем понятна суть такого взаимодействия, а следовательно не видно где синхронизировать...

Автор: Anton Vatchenko 21.12.2006, 18:58
1. Синхронизовать нужно только в закрытии потока.
2. Они работают с одними данными, которые синхронизированы.

То есть есть один поток, который следит за остальными. Эти остальные потоки между собой не работают. Они могут послать команды главному потоку, и поток может послать каждому из них команды. Не иначе.

Автор: Shurr 21.12.2006, 19:53
Ок, тогда такой вопрос: по логике работы если поток завершил работу во время апдейта - он должен подождать пока его не закончат апдейтить, или должен прекратиться апдейт?

Автор: s8e8r8g8e 21.12.2006, 20:22
вроде бы если вначале апдейта не залочить какойнибудь объект до снятия лока на который все потоки не могут завершиться то проблема будет что апдейт может попробовать работать с уддалённым из вектора потоком(точнее обратится по несуществующему индексу наример, или по этому индексу будет уже другой поток), или что-то не так?
а вот почему может быть проблема при апдейте завершённого потока, ну завершён, ну пройдёт апдейт впустую (ну пусть данные в нём обновятся) ну ниначто это не повлияет ну и что с того smile?

Автор: Anton Vatchenko 22.12.2006, 14:50
В том то и дело, что если поток умрет, то нужно работать не с ним, а с чем-то другим (например, записать неотправленные в базу данных).

Автор: Shurr 22.12.2006, 15:17
Честно говоря суть подобного взаимодействия настолько неясна, что посоветовать что-то конкретное очень сложно. Из того что я вижу можно предложить пару решений, но не знаю насколько они подойдут:

1. Организовать поддержку транзакций. 
Весь Update потока происходит в одной транзакции. Перед окончанием апдейта происходит проверка: если поток еще жив - коммит транзакции, если нет - откат.

2. Добавить проверку на "живость" потока в методы класса MyThread, при помощи которых наблюдающий поток взаимодействует с ним (я так понимаю, их должно быть немного). В случае если поток уже завершил свою работу - выбрасывать исключение. В наблюдающем потоке исключение отлавливать и соответствующим образом обрабатывать.


Да, и еще одно: лучше не работать напрямую с вектором в таком виде, как это представлено в примере. Если есть коллекция, содержимое которой будет меняться из разных потоков - то для пробегания по ее элементам стоит написать специальный синхронизированный итератор.

Автор: Anton Vatchenko 25.12.2006, 13:08
Спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)