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


Автор: Platon 23.5.2007, 09:40
Здравствуйте, уважаемые.

Встала проблема в синхронизации.

Код

public class WriteThread implements Runnable {
    private LinkedList<Message>messageQueue = new LinkedList<Message>();
    private OutputStream os;
    private boolean isWorking;
    public WriteThread(OutputStream os) {
        this.os = os;
    }

    public synchronized void sendMessage(Message message) {
        messageQueue.addLast(message);
        if (!isWorking) {
            System.out.println("start thread");
            (new Thread(this)).start();
        }
    }

    public void run() {
        isWorking = true;
        while (!messageQueue.isEmpty())
            try {
                Message message = messageQueue.pop();
                if (Options.DEBUG)
                    System.out.println("Start to upload Message: " + message);
                message.upload(new DataOutputStream(os));
                if (Options.DEBUG)
                    System.out.println("Message sent             " + message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        isWorking = false;
    }
}


2 сообщения, по идее должно отправляться 
Цитата

Start to upload Message: Auth message  User List size = 1 UserInfo record_id = 1 login = "Platon" rating = "0"
Message sent             Auth message  User List size = 1 UserInfo record_id = 1 login = "Platon" rating = "0"
Start to upload Message: System message 
Message sent             System message

а шлется
Цитата

Start to upload Message: System message 
Start to upload Message: Auth message  User List size = 1 UserInfo record_id = 1 login = "Platon" rating = "0"
Message sent             Auth message  User List size = 1 UserInfo record_id = 1 login = "Platon" rating = "0"
Message sent             System message

и в отдельных потоках, а не в одном как хотелось бы.

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

Автор: Platon 23.5.2007, 11:27
Цитата

Код

public synchronized void sendMessage(Message message) {
        messageQueue.addLast(message);
        if (!isWorking) {
            System.out.println("start thread");
            (new Thread(this)).start();
        }
    }


Сделаю предположение, что  sendMessage synchronized, и глупо поступаю когда в конструкторе сообщаю new Thread(this) и потом стартую, выходит, что стартовать он не сможет до тех пор, пока this synchronized. и изменить isWorking соответственно не сможет, как же правильно разрулить ситуацию?

я попробовал сделать 
Код

public synchronized void sendMessage(Message message) {
        messageQueue.addLast(message);
        if (!isWorking) {
            isWorking = true;
            System.out.println("start thread");
            (new Thread(this)).start();
        }
    }

но чревато ли это чем нибудь?

Автор: chief39 23.5.2007, 13:12
Ну, по идее, пришёл ты в сендмесседж, запустил тред. Ничего странного в том, что джвм выполнила все действия по запуску треда, а потом система решила что пора и другие треды пощёлкать. Если это произойдёт до того, как изВоркинг установится в тру - то запустится ещё раз тред.

Это потому что запуск и пометка о запуске происходят у тебя не в одном синхронайзд блоке.
Попробуй перенести

Цитата(Platon @  23.5.2007,  09:40 Найти цитируемый пост)
isWorking = true;

в
Цитата(Platon @  23.5.2007,  09:40 Найти цитируемый пост)
System.out.println("start thread");
            (new Thread(this)).start();

Сразу перед (new Thread(this)).start();.
То есть ты уже в стадии запуска, ставишь а-ля свой лок на повторный запуск треда и собсно, запускаешь его следующей строчкой. Это гарантирует что никто не вклинится между тем как ты его запустил и тем, как он начал выполнять своё тело.
Кроме того, ставь именно перед, чтоб он приходил в метод run с уже гарантированно установленным isWorking

Автор: Platon 23.5.2007, 23:12
Угу, я именно так и сделал. Спасибо.

Автор: chief39 24.5.2007, 13:16
Тогда пометь решённым  smile 

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