Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Java: Общие вопросы > Последовательный запуск Thread |
Автор: AbdulBcex 30.6.2010, 18:09 | ||
Всем здравствовать! Наткнулся тут на проблему. Есть класс наследующий класс, который имплементирует Runnable. Делаю @Override метода run();
Код с комментами взят из метода суперкласса, я его не трогал. Объясните, пожалуйста, что это значит? А собственно вопрос таков. Я делаю несколько объектов класса. У каждого вызываю метод start(), один за другим. Нужно, чтобы первый объект сразу переходил "к делу" - у него OFFSET = 0, у второго - 25 (50 и 75 у других соответственно). Смотрю на данные логов - ну свистопляска чистой воды! Первые значений 20 выходят практически ровно, разница в сотых долях. Потом такие скачки начинаются, аж жуть. Забавно, но ведь по идее один поток стартует сразу, второй спит 25 мс... Причем делаю на разных компьютерах, на одном JVM специально выделено отдельное ядро и гигабайт оперативки - всегда разный результат и те же скачки. Попробовал Thread.sleep(OFFSET, 0);, так он мне потом вообще разницу в 7(!) мс вместо 25 выдал. Поискал тут на форуме, видел похожие темы, но они либо старые, либо не совсем то. Подскажите, пожалуйста, где поискать-посмотреть-почитать, что ли. |
Автор: LSD 30.6.2010, 19:32 |
1. sleep() не гарантирует что поток будет остановлен ровно на Х мсек. Это время приблизительное. И вообще он может проснутся раньше, смотри документацию. 2. Разрешаюшая способность таймера тоже не 1 мсек, а больше, под виндой это где-то 10 мсек. 3. Нет никаких гарантий на тему того, как система будет переключать потоки. Даже если у тебя N потоков и N ядер, это вовсе не гарнтирует что каждому потоку будет выделенно отдельное ядро и они на самом деле будут выполнятся паралельно. А уж в случае одного ядра, переключение между потоками просто гарантированно. Плюс запись логов задача связанная с блокировками на синхронизацию, обращение к внешним ресурсам (например система IO), что так же вызывает переключение потоков. Если ты хочешь получить какой-то гарантированный порядок - используй синхронизацию или java.util.concurrent. |
Автор: Skipy 30.6.2010, 21:15 |
Почитайте про синхронизацию: http://www.skipy.ru/technics/synchronization.html |
Автор: AbdulBcex 1.7.2010, 15:03 |
Спасибо за советы. На самом деле синхронизация действительно единственное, что приходит в голову. Но она требует объект, которого нет, который нужно сделать только для синхронизации. Опять же блоки synchronize и т.д., которые не ясно где ставить, метода main у меня нет, потоки принадлежат разным объектам одного класса, которые между собой никак не взаимодействуют, и не особо радует перспектива это взаимодействие создавать. Нужно-то всего лишь притормозить запуск каждого следующего потока на данное количество мс. Я делал до четырех потоков, так несмотря ни на что (на их количество и параллельную работу, например), данные они возвращали четко с заданной переодичностью, то есть data(i) - data(j) = const мс. В общем, думаю дальше. |
Автор: LSD 1.7.2010, 15:45 | ||
Так чего тебе все таки надо: организовать паралельную работу нескольких потоков или красиво вывеси в консоль:
через заданные интервалы времени? Если второе то просто используй java.util.Timer. |
Автор: AbdulBcex 2.7.2010, 14:05 | ||||
Да видимо объяснить толково не очень выходит ![]() Есть n потоков. Каждый поток организуется n-ным объектом класса:
Каждый следующий поток стартует через OFFSET = n*25 мс (т.е. 0 - сразу, 1 - 25 мс, 2 - 50, 3 - 75 мс и т.д.) начинает давать данные с периодом Т. OFFSET я задаю через
Ну а дальше уже внутри метода есть считалки через System.nanoTime() дающие тот самый период. И все бы было ничего, если б не восьмой этаж и то, что где-то в середине именно считалки дают сбой - т. е. вместо T идет период T+(-)some_time. Такого рода отклонения ловятся с помощью прибавки/убавки времени. Т.е. в следующий раз компенсируется с помощью T-(+)some_time. Вот. Такие дела. Выглядит сложновато, наверное, но как по мне, так это проще, чем выдумывать синхронизацию на пустом месте. В принципе, работает. Сейчас свистопляски не наблюдается особой. Более менее приближено к прямой, даже средние значения T лежат в пределах +-10мс, (хотя и то много, но это максимум, что наблюдал до сего времени). Еще не видел, что такое java.util.cocurrent, но если про параллельную работу с объектами, то мне как-то не очень. |
Автор: AbdulBcex 5.7.2010, 11:42 | ||
Не совсем. Поток генерирует данные, раз в 100 мс, с временными отметками (timestamp), каждый - свои (т.е. неодинаковые), а потом передает их дальше (не другим потокам, а дальше по цепочке). Задержка нужна, чтобы более четко и вовремя заполнять стеки приемников данных, поскольку данные, к примеру, первого потока будут идти дольше - их еще обработать нужно, в то время как данные четвертого идут сразу в стек приемника. В общем, работаю над синхронизацией. Слишком уж нестабильно без нее. Для себя сделал вывод: хочешь организовать параллельную работу даже не имеющих отношения друг к другу потоков - synchronize. Хотя уже сейчас вижу, что в принципе это нелегко даже с синхронизацией. Стало лучше, но до нормальных (и более менее постоянных) результатов еще далеко. |
Автор: AbdulBcex 7.7.2010, 12:47 | ||
И снова здравствуйте!!! Извиняюсь, что "бужу" тему. Подскажите, пожалуйста, как синхронизировать разные потоки, созданные разными объектами одного класса. Я слегка замумукался - все примеры идут для синхронизации объекта или метода одного класса, для доступа потоками других классов. Мне же нужно, по сути, синхронизировать внутри одного метода run(), выполняемого в последствии каждым из этих потоков. Вот мой код:
Путем экспериментов выяснил, что
|
Автор: 4EJIOBEK 8.7.2010, 11:13 |
Ваш класс не описывает интерфейс Runnable не является наследником Thread. Как вы используете свой класс(стартуете его в потоке)? |
Автор: AbdulBcex 8.7.2010, 12:43 |
Я все это еще в первом посте описал вроде ![]() |