Кто-нибудь видит какие-либо проблемы с этим шаблоном потока? - PullRequest
3 голосов
/ 10 июня 2010

Вот простой шаблон потока, который я использую при написании класса, которому нужен только один поток, и для которого требуется определенная задача.

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

public class MyThread implements Runnable {
    private boolean _exit = false;
    private Thread _thread = null;

    public void start () {
        _exit = false;

        if (_thread == null) {
            _thread = new Thread(this, "MyThread");
            _thread.start();
        }
    }

    public void run () {
        while (!_exit) {
            //do something
        }
    }

    public void stop () {
        _exit = true;

        if (_thread != null) {
            _thread.interrupt();
            _thread = null;
        }
    }
}

Я ищу комментарии вокруг, если я что-то упустил или есть лучший способ написать это.

Ответы [ 6 ]

6 голосов
/ 10 июня 2010

Я бы посоветовал не использовать класс Thread напрямую. Платформа Executors, доступная начиная с Java 5, упрощает многие проблемы, связанные с многопоточностью. Идея состоит в том, что ваш класс будет выполнять требуемую задачу, а все функции управления потоками будут выполняться Исполнителем, что избавит вас от необходимости справляться со сложностью потоков.

Хорошую вводную банку на платформе Java Executors можно найти здесь .

2 голосов
/ 10 июня 2010

Ну, сам класс не является потокобезопасным. Это не обязательно проблема, если это задокументировано и наблюдается в коде. Если это не так, вы можете потерять ссылки на объекты Thread, которые будут работать параллельно, если два метода получат одновременно метод start ().

Флаги, используемые в качестве семафоров, также, конечно, должны быть нестабильными.

API класса немного странный. Вы реализуете Runnable, говоря другим классам «используйте мой метод run для вызова меня», но затем имитируете метод start полного объекта Thread. Вы можете скрыть метод run внутри внутреннего класса. В противном случае это несколько сбивает с толку, как предполагается использовать объект.

И, как всегда, любая схема, которая включает в себя слова new Thread(), а не использование пула, несколько абстрактна. Хотелось бы знать о том, что вы на самом деле делаете с этим, чтобы действительно разумно прокомментировать это.

2 голосов
/ 10 июня 2010
  1. Сделайте логический флаг изменчивым.
  2. При вызове stop не прерывайте поток, а просто установите для флага _exit значение true.
  3. Если вы собираетесьдля прерывания, затем поместите try / catch / finally вокруг цикла while и поймайте исключение прерывания, очистите состояние объектов, с которыми вы работаете, и выйдите. И будьте осторожны, чтобы не вызвать тупик!
  4. Наконец, вы можете использовать CountDownLatch или что-то в этом роде, чтобы сигнализировать о завершении потока.

Другая вещь - это спор ... вы не показываете ничего, что будет изменено потоком, поэтому в зависимости от того, что модифицируется, вам может потребоваться синхронизация (блокировка и т. Д.).

1 голос
/ 10 июня 2010

1) Вы должны объявить _exit как volatile, чтобы предотвратить проблемы видимости потока.Если stop () может вызываться несколькими потоками, _thread также должен быть изменяемым.

2) При вызове прерывания возникает исключение InterruptedException только для операций прерываемой блокировки.Вам может потребоваться выполнить больше действий, в зависимости от того, какие блокирующие операции вы выполняете в потоке

3) Если вы хотите, чтобы экземпляры класса можно было повторно использовать, вам следует установить для _exit значение false в методе start ().

0 голосов
/ 10 июня 2010

Переменная _exit должна быть изменчивой.Кроме того, было бы полезно следовать более нормальному соглашению о кодировании.: -)

0 голосов
/ 10 июня 2010

Я бы предпочел защищенный блок (http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html) на 'this'. Вы можете уведомить поток, чтобы он очень быстро вышел из цикла, а затем снова проверить 'готовый' var. обычно используют Thread.sleep (x), вы используете this.wait (x) с синхронизированным (this) блоком вокруг всего цикла. Вы также должны быть в синхронизированном (this) блоке для вызова this.notifyAll ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...