Comments 97
Запустить новый поток можно двумя способами:
Еще можно через новый интерфейс java.util.concurrent.Callable
И еще один момент — InterruptedException нежелательно поглощать без обработки (пустой catch блок), его нужно либо повторно генерировать, либо заново выставить флаг методом interrupt(), чтобы еще «прервать» текущий поток. Иначе другие методы в стеке вызовов не узнают, что было прерывание.
0
Да, про Callable я забыл, а если честно то и вовсе не знал) Насколько я понимаю возвращение результата работы потока используется не слишком часто, но, все равно, напишу об этом в следующей статье.
Насчет исключения — честно говоря я не очень понимаю зачем другим методам в стеке знать о возникнувшем исключении, если после его возникновения требуется просто продолжить выполнение вызвавшего метода. Может поясните?
Насчет исключения — честно говоря я не очень понимаю зачем другим методам в стеке знать о возникнувшем исключении, если после его возникновения требуется просто продолжить выполнение вызвавшего метода. Может поясните?
+1
Насколько я понимаю возвращение результата работы потока используется не слишком часто
Чаще используется возможность выбросить исключение.
честно говоря я не очень понимаю зачем другим методам в стеке знать о возникнувшем исключении,
Допустим вы в рамках одного потока поймали InterruptedException, например, в методе sleep и поглотили его без выставления флага. Если дальше по коду (или выше по стеку) стоят проверки флага Interrupted — то они не сработают
0
Допустим вы в рамках одного потока поймали InterruptedException, например, в методе sleep и поглотили его без выставления флага. Если дальше по коду (или выше по стеку) стоят проверки флага Interrupted — то они не сработают
Ну, это было бы косяком если бы кто-то собирался прерывать потоки из примеров) В примере с объяснением прерываний обработка исключения выполняется (а именно вызывается return), в других примерах особого смысла раздувать код не вижу. Однако в более «жизненных» ситуациях работать с исключениями, конечно, надо по-другому.
0
Вы, наверное, имеете большой опыт проведения собеседований по Java Concurrency…
+2
Статья освежила память, спасибо.
Но вот за
мне бы за такое руки оторвали в универе.
Но вот за
class SomeThing //Нечто, реализующее интерфейс Runnable
implements Runnable //(содержащее метод run())
мне бы за такое руки оторвали в универе.
+2
*спрятал руки за спину* хыхы)
+1
Освежила память? Мне казалось это основы, которые должны после недельного запоя от зубов отскакивать :)
+2
Простите, а что здесь не так? (без сарказма)
+1
а что не так с этим кодом?
+1
Разделение на главный/побочный потоки возникает лишь в голове программиста, на уровне JVM таких разделений нет.
0
Согласен, в Java потоки равноправны.
0
Не совсем, точнее даже так, не для каждой JVM. У треда как минимум может быть приоритет, который поддерживается не всеми ОС. Но так же тред может быть помечен как daemon, т.е. он не будет для JVM считаться полноценным тредом и и она, например, может его попросту убить, если все нормальные (т.е. не daemon) треды будут убиты или закончат свое исполнение
0
private boolean mFinish = false;
Обязательно volatile, иначе другой поток может не увидеть изменений данной переменной, сделанных в методе finish() другим потоком (при опции jit компилятора -server).
Обязательно volatile, иначе другой поток может не увидеть изменений данной переменной, сделанных в методе finish() другим потоком (при опции jit компилятора -server).
+4
Хм, спасибо. Думаю в данном примере это не критично, но о
volatile
расскажу в следующей статье.-1
Ничего себе «не критично». Вы не объявили переменную volatile, не используете synchronized блок, пишите в неё из одного потока, а читаете с другого — по спецификации Вам не гарантируется, что изменения в переменной другой поток увидит даже к завтра. И Вы хотите учить других такой статьей?
+14
Я понимаю ваше негодование, но формат статьи не позволяет описать все и сразу. В нормальном режиме компиляции программа работает. На данном этапе не вижу смысла требовать большего. Никто не ринется писать многопоточные программы, сразу после прочтения данной статьи, пока не разберется что к чему. Статья служит точкой старта а не полным руководством. О volatile, syncronized и разделении ресурсов между потоками будет рассказано в следующей статье.
-5
А причём тут другая статья? Код в этой статье написано неправильно, он вполне может повиснуть на одной из реализаций виртуальной машины, и это будет валидное поведение. Я бы сказал, что это даже более вероятно, и если оно где-то работает, то это больше чудо в следствии недоработанного оптимизатора.
Вам лучше исправить это, а не рассказывать, что это «не критично» да про какой-то «нормальный режим компиляции».
Вам лучше исправить это, а не рассказывать, что это «не критично» да про какой-то «нормальный режим компиляции».
+8
зато формат статьи позволяет написать правильный код c
volatile
, сказав, что про это слово будет следующая статья.+1
А смысл, зачем еще один пересказ? Об этом писали уже сто раз, в том числе и на хабре, можно просто ссылку оставить.
0
Спасибо большое автору за пост, посоветуйте пожалуйста еще статьи и книги о потоках, желательно из реальной жизни, а то большинство материала довольно абстрактно или устарело. Было бы замечательно увидить еще посты на данную тематику.
0
Для начала сойдет, но как сказано документация и исходники — вот основа знаний о Java.
Касательно многопоточности могу посоветовать след. книгу — «Concurrency in practice»(если не ошибаюсь только на англ. языке).
Касательно многопоточности могу посоветовать след. книгу — «Concurrency in practice»(если не ошибаюсь только на англ. языке).
0
А еще Java 2: наиболее полное руководство. Шилдт
0
читайте Java Concurrency in Practice. Там всё есть. И без грубых ошибок, как в этой статьи.
+4
Спасибо за советы и названия книг, Эккеля читал, но слишком много описания классов и мало понятно, как все это в итоге использовать. Про Шилдта забыл, честно говоря, хотя самая пожалуй очевидная книга, которую надо было смотреть. Java Concurrency in Practice — много о ней слышал, надо будет купить. Мне больше всего понравился подход в книге — Java 7 Recipes A Problem-Solution Approach, там то, как раз показано на примерах, как применять многопоточность и как распараллеливать алгоритмы, но примеров к сожалению не так много.
Основная моя проблема и моих коллег по работе, в том, что имея более пяти лет опыта разработки на java никто из нас ни разу не использовал многопоточность. Для меня до сих пор не вполне ясно, какие проблемы и как я могу решить используя multi-threading. Хотелось бы простого объяснения вида: проблема -> решение +объяснение подводных камней, а не только описания всех классов пакета, с тоннами кода.
Основная моя проблема и моих коллег по работе, в том, что имея более пяти лет опыта разработки на java никто из нас ни разу не использовал многопоточность. Для меня до сих пор не вполне ясно, какие проблемы и как я могу решить используя multi-threading. Хотелось бы простого объяснения вида: проблема -> решение +объяснение подводных камней, а не только описания всех классов пакета, с тоннами кода.
0
Основная моя проблема и моих коллег по работе, в том, что имея более пяти лет опыта разработки на java никто из нас ни разу не использовал многопоточность.
так может, оно Вам и не надо? Может, это и не проблема?
Для меня до сих пор не вполне ясно, какие проблемы и как я могу решить используя multi-threading
дык зачем Вам многопоточность тогда?
Хотелось бы простого объяснения вида: проблема -> решение +объяснение подводных камней, а не только описания всех классов пакета, с тоннами кода.
читайте Java Concurrency in Practice
+1
Нет проблемы — это лучшее состояние!
Многопоточные программы писать трудно, а хорошие многопоточные программы — очень трудно. Там проще налажать. Поэтому если у меня есть возможность написать в один поток — я всегда пишу в один. И только если я не вижу других путей для ускорения — начинаю заморачиваться с многопоточностью, стараясь при этом использовать примитивы высокого уровня.
Особая тема — многопоточность и GUI. Но это совсем отдельная песня.
Многопоточные программы писать трудно, а хорошие многопоточные программы — очень трудно. Там проще налажать. Поэтому если у меня есть возможность написать в один поток — я всегда пишу в один. И только если я не вижу других путей для ускорения — начинаю заморачиваться с многопоточностью, стараясь при этом использовать примитивы высокого уровня.
Особая тема — многопоточность и GUI. Но это совсем отдельная песня.
+2
Интересное мнение и точка зрения, обязательно учту. Область деятельности у меня не связана с промышленной разработкой, а связана с академической и научной деятельностью и я, как и окружающии меня люди, не привык думать о том как распараллелить алгоритм и меня этому никто не учил и спросить тоже неукого. Вот, если к примеру, я анализирую объекты при помощи reflection и объектов десятки тысяч, то думаю для такого рода алгоритмов можно использовать многопоточность и это даст определенный прирост в производительности.
Именно об этом и хотелось бы прочесть, как и зачем использовать многопоточность и будет ли игра стоить свеч. Да и скилл программирования тоже хочется улучшить.
Именно об этом и хотелось бы прочесть, как и зачем использовать многопоточность и будет ли игра стоить свеч. Да и скилл программирования тоже хочется улучшить.
0
Основная моя проблема и моих коллег по работе, в том, что имея более пяти лет опыта разработки на java никто из нас ни разу не использовал многопоточность.
Я думаю следует сказать спасибо всем тем, кто позволил большинству программистов даже не задумываться о том, что они в 99.9% случаев используют многопоточность в решении своих проблем. Остальные 0.089 — это студенты которые решают всевозможные академические задачи, и оставшиеся — люди, которые понимают почему они отказываются от многопоточности.
Хотелось бы простого объяснения вида: проблема -> решение +объяснение подводных камней, а не только описания всех классов пакета, с тоннами кода.
Проблема: игровой сервер, способный тянуть на себе несколько тысяч пользователей на одной ноде. Соединения постоянные, игроки всю игру взаимодействуют друг с другом (пачками по 2-9 человек).
Решение: netty в для обработки клиент-серверного и сервер-серверного (серверов то может быть много) взаимодействия, что бы не писать всю низкоуровневую мишуру с соединениями вручную. Остальное — многопоточность.
Объяснение: все, что есть сейчас в мире java для EE не подходит, потому что потребуется либо 20+ серверов, что экономически не выгодного. Либо попросту не будет справляться с такими нагрузками. Ну и главный аргумент — оно все http, что нам категорически не подходит.
Я думаю следует сказать спасибо всем тем, кто позволил большинству программистов даже не задумываться о том, что они в 99.9% случаев используют многопоточность в решении своих проблем. Остальные 0.089 — это студенты которые решают всевозможные академические задачи, и оставшиеся — люди, которые понимают почему они отказываются от многопоточности.
Хотелось бы простого объяснения вида: проблема -> решение +объяснение подводных камней, а не только описания всех классов пакета, с тоннами кода.
Проблема: игровой сервер, способный тянуть на себе несколько тысяч пользователей на одной ноде. Соединения постоянные, игроки всю игру взаимодействуют друг с другом (пачками по 2-9 человек).
Решение: netty в для обработки клиент-серверного и сервер-серверного (серверов то может быть много) взаимодействия, что бы не писать всю низкоуровневую мишуру с соединениями вручную. Остальное — многопоточность.
Объяснение: все, что есть сейчас в мире java для EE не подходит, потому что потребуется либо 20+ серверов, что экономически не выгодного. Либо попросту не будет справляться с такими нагрузками. Ну и главный аргумент — оно все http, что нам категорически не подходит.
0
Прямо-таки грубых?)
0
Да что вы, какая же это грубая ошибка, так, мелочь: подумаешь в одном случае другие потоки не смогут увидеть изменения переменной (отсутствие volatile), а в другом так и вовсе в гонке мы можем потерять несколько инкрементов\декрементов (отсутствие синхронизации).
Но зато мы можем рассказывать о том, что же такое многопоточность, видимо не разу не использовав ее для решения реальных задач.
И да, вы хотя бы посмотрели исходники прежде чем писать глупости про Thread.sleep() например.
Но зато мы можем рассказывать о том, что же такое многопоточность, видимо не разу не использовав ее для решения реальных задач.
И да, вы хотя бы посмотрели исходники прежде чем писать глупости про Thread.sleep() например.
+2
подписываюсь
0
Volatile добавил, про необходимость синхронизации написал в заключении. Что не так с методом Thread.sleep()?
0
То есть ты хочешь, что бы я сюда скопировал код данного метода?
0
Лучше скажите в каком разделе ошибка и в чем она.
0
Хорошо, если вы сами не в состоянии, кину код сюда:
/**
* Causes the currently executing thread to sleep (cease execution)
* for the specified number of milliseconds plus the specified number
* of nanoseconds, subject to the precision and accuracy of system
* timers and schedulers. The thread does not lose ownership of any
* monitors.
*
* @param millis the length of time to sleep in milliseconds.
* @param nanos 0-999999 additional nanoseconds to sleep.
* @exception IllegalArgumentException if the value of millis is
* negative or the value of nanos is not in the range
* 0-999999.
* @exception InterruptedException if any thread has interrupted
* the current thread. The <i>interrupted status</i> of the
* current thread is cleared when this exception is thrown.
* @see Object#notify()
*/
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
0
Хм, получается время ожидания все-равно округляется до миллисекунд?
0
исправил
0
Вообще можно было не исправлять. У Вас же в статье нигде не говорится, что речь идёт про конкретную реализацию VM, тем более от Oracle. Oracle может и округлили (для совместимости между различными ОС, т.к. в венде с наносекундами имплементировать паузу сложно), а другие могут и не округлять. Например, Google в своей Dalvik VM использует эти наносекунды без округлений.
+1
Вам нравится меня мучать? :) Вернул всё как было.
0
Ну теперь там есть фраза «При вызове этого метода JVM честно передает системе наносекунды, если система это поддерживает», а это неверно. Linux всё поддерживает, но Oracle JVM это не юзает. Нельзя же говорить за все реализации JVM.
0
Я вернул все назад, первый вариант был самым лояльным.
p.s. а линукс разве поддерживает интервалы прерываний меньше 1мс? Пока я искал информацию по методу sleep я натыкался на высказывания по поводу 10мс у windows и 1мс у линукса. Или я в чем-то заблуждаюсь?
p.s. а линукс разве поддерживает интервалы прерываний меньше 1мс? Пока я искал информацию по методу sleep я натыкался на высказывания по поводу 10мс у windows и 1мс у линукса. Или я в чем-то заблуждаюсь?
0
Как-то плохо Вы гуглили. Первые ссылки в гугле ведут на пост в блоге разработчика Oracle VM, где есть фраза: «On Solaris and Linux these calls take time structures that allow microsecond, or nanosecond, values to be passed — but there is no guarantee of that resolution being achieved». В Linux точность таймера очень сильно зависит от того, с какими параметрами скомпилировано было ядро.
0
Java Concurrency Guidelines
0
Зря ничего не написано про синхронизацию потоков прекрасными методами wait и notify.
0
Синхронизация — довольно большая тема, я не хотел растягивать статью. О синхронизации я напишу в следующей статье.
0
Не знаю, к счастью или сожалению, но после того, что предлагает пакет java.util.concurrent методы wait и notify ставновятся уже не такими прекрасными. Про опыты практического примеренния дуамаю даже не стоит и вспоминать
0
подписываюсь
0
Ну почему, есть задачи, которые через synchronized/wait/notify решаются несколько лаконичнее, чем через аналогичные ReentrantLock/lock/unlock из java.util.concurrent
0
Хотелось бы увидеть пример задачи. Особенно с wait/notify. Вот по поводу synchronized — я еще согласен, написал его в объявлении метода и можно спать спокойно.
0
Пример задачи. Поток каждые 60 секунд сканирует папку на наличие изменений:
Теперь нужно добавить метод, который принудительно сканирует папку, т.е. пробуждает поток из состояния ожидания и делает немедленный скан.
С ReentrantLock все было бы то же самое, но чуть длиннее
public void loop()
{
for (;;)
{
scan();
synchronized(lock)
{
lock.wait(60, TimeUnit.SECONDS);
}
}
}
Теперь нужно добавить метод, который принудительно сканирует папку, т.е. пробуждает поток из состояния ожидания и делает немедленный скан.
public void forceScan()
{
synchronized(lock)
{
lock.notify();
}
}
С ReentrantLock все было бы то же самое, но чуть длиннее
0
Кстати, насчет wait/notify. Посмотрите класс Monitor из библиотеки Guava. Это более простая и удобная альтернатива стандартным Lock/Condition. Там есть несколько принципиальных отличий: не нужно вызывать методы signal/signalAll, не нужно проверять условие в цикле. В общем, классная вещь, но к сожалению, пока только Beta.
0
Про синхронизацию «прекрасными» методами wait, notify/notifyAll, join, yield следует написать следующее: «используйте только в крайнем случае, например, при решении задач на собеседованиях, если вам явно указали что следует использоваться только данные примитивы»
+1
не зря. Ничего замечательного в них нету. С Java5 приехало много высокоуровневых примитивов. Насколько я помню, сейчас рекомендуется использовать именно их, а wait-notify только в двух случаях:
1. иначе никак
2. legacy code
Хотя для первого случая есть мозг, а для второго — рефакторинг.
1. иначе никак
2. legacy code
Хотя для первого случая есть мозг, а для второго — рефакторинг.
+1
Есть ещё третий случай, когда использование низкоуровневых средств оправдано требованием быстродействия.
0
ооо, а можно пример в студию?
0
Те «высокоуровневые примитивы» построены обычно как обёртки над низкоуровневыми, т.е. быстрее быть не могут по определению. Потому иногда имеет смысл написать свой велосипед, не такой универсальный как стандартный, а заточенный под конкретную задачу. Пример такого велосипеда приводить не вижу смысла.
0
Те «высокоуровневые примитивы» построены обычно как обёртки над низкоуровневыми,
не всегда. Всё чаще это Unsafe, быстрее которого сделать сложно.
т.е. быстрее быть не могут по определению.
а нативно?
Потому иногда имеет смысл написать свой велосипед, не такой универсальный как стандартный, а заточенный под конкретную задачу.
ну если вы — твиттер, гугл, фейсбук или дойчбанк, то да, безусловно. В остальных случаях — не уверен.
0
> а нативно?
Нативно реализовать на Си? Ну оно то будет быстрее, но там Вы точно не будете юзать те «высокоуровневые примитивы» о которых говорили. ;)
>ну если вы — твиттер, гугл, фейсбук или дойчбанк
Вот как раз они могут себе позволить купить лишний сервер. И потому иногда не заморачиваются, а отдают приоритет надёжности и проверенности. А нам, простым смертным, приходится извращаться.
Нативно реализовать на Си? Ну оно то будет быстрее, но там Вы точно не будете юзать те «высокоуровневые примитивы» о которых говорили. ;)
>ну если вы — твиттер, гугл, фейсбук или дойчбанк
Вот как раз они могут себе позволить купить лишний сервер. И потому иногда не заморачиваются, а отдают приоритет надёжности и проверенности. А нам, простым смертным, приходится извращаться.
0
с нативностью — это вообще отдельная история, давайте забудем об этом.
Я уточню свою мысль: высокоуровневыми примитивами из java.uril.concurrent можно обойтись в 99 процентах случаев.
Что касается крупных компаний — речь идёт не о лишем сервере, а о лишних десятках, сотнях и даже тысячах серверов. Поэтому им имеет смысл поинженерить. Тот случай, когда пара инженеромесяцев выйдут дешевле закупки сотни серверов. А вот для мелких компаний — дешевле часто купить сервер, чем тратить инженеро-месяцы на решение задач оптимизации.
Я уточню свою мысль: высокоуровневыми примитивами из java.uril.concurrent можно обойтись в 99 процентах случаев.
Что касается крупных компаний — речь идёт не о лишем сервере, а о лишних десятках, сотнях и даже тысячах серверов. Поэтому им имеет смысл поинженерить. Тот случай, когда пара инженеромесяцев выйдут дешевле закупки сотни серверов. А вот для мелких компаний — дешевле часто купить сервер, чем тратить инженеро-месяцы на решение задач оптимизации.
0
Свой велосипед просто может глючить по началу, крупным компаниям такое не к лицу, потому в некоторых случаях предпочтительнее использовать проверенные средства.
А вот для мелких точно так же может оказаться дешевле потратить месяц работы программиста с окладом 1000 долларов, чем купить новый сервер ценой в 10000 долларов, особенно если их просто нет. Пускай даже потом придётся 3 месяца ещё вылавливать баги.
Ну… это уже экономика, думаю её тоже можно оставить в покое.
А вот для мелких точно так же может оказаться дешевле потратить месяц работы программиста с окладом 1000 долларов, чем купить новый сервер ценой в 10000 долларов, особенно если их просто нет. Пускай даже потом придётся 3 месяца ещё вылавливать баги.
Ну… это уже экономика, думаю её тоже можно оставить в покое.
0
ну и насчёт
Загляните в код AtomicInteger, что ли… Или в Semaphore. Найдите там хоть один wait или notify…
«высокоуровневые примитивы» построены обычно как обёртки над низкоуровневыми
Загляните в код AtomicInteger, что ли… Или в Semaphore. Найдите там хоть один wait или notify…
0
Да, соглашусь, в данном случае это обёртки не над wait/notify.
Но AtomicInteger — это вообще из другой оперы… там и не надо wait/notify. Если уж сравнивать, то с классом, предоставляющим аналогичные возможности, там Condition, например. Вот если дойдут руки попробую даже как-то сравнить количественно разность в скорости работы для типовой задачи.
Но AtomicInteger — это вообще из другой оперы… там и не надо wait/notify. Если уж сравнивать, то с классом, предоставляющим аналогичные возможности, там Condition, например. Вот если дойдут руки попробую даже как-то сравнить количественно разность в скорости работы для типовой задачи.
0
если дойдут руки попробую даже как-то сравнить количественно разность в скорости работы для типовой задачи.
Задолбаетесь сравнивать. Слишком много граблей, на которые можно наступить. И слишком много конфигураций придётся проверить.
Если уж сравнивать, то с классом, предоставляющим аналогичные возможности, там Condition, например.
у него две реализации: ConditionObject в AbstractQueuedSynchronizer и в AbstractQueuedLongSynchronizer. Через первый работает куча java.util,concurrent-примитивов: Semaphore, CountDownLatch, ReetrantLock, ThreadpoolExecutor и пр. Второй — вариант AbstractQueuedSynchronizer для специального случая.
AtomicInteger — это вообще из другой оперы… там и не надо wait/notify
Речь о том, что есть целый класс высокоуровневых примитивов, которым wait/notify вообще ни в какое место не впились.
0
Это когда JIT вырезает синхронизацию посредством synchronized?
0
Вы имеете ввиду случай, когда JIT оптимизирует вход/выход в монитор? Ну это тоже — модный ReentrantLock, который использует CAS-инструкции и должен быть теоретически куда быстрее стандартного явовского монитора (блоки synchronized), оказывается очень часто медленнее. :)
0
Я имею в виду то, что JIT умеет вырезать полностью всю синхронизацию если она не требуется. По поводу стандартного монитора могу сказать вот что…
Во-первых это три типа синхронизации: biased, thin и fat, а не одна.
biased — самый простой и быстрый тип блокировки, при помощи cas-а (как я помню единственного) биндится к одному и тому же потоку, если он постоянно захватывает монитор. Накладные расходы минимальны. Если в дело вступает другой поток, то тип меняется на следующий
thin — перепривязка монитора происходит уже каждый раз с cas-ом. Происходит до тех пор пока множество потоков не начинает биться за ресурс и дальше мы спускаемся выше, к fat
fat — тут уже используются примитивы ос, что весьма и весьма затратно.
Собственно я думаю я ответил на вопрос почему non-fair* RL часто медленнее стандартного монитора (много оптимизаций со стороны JVM, в то время как RL не трогается)
*fair по своей сути будет в тысячи раз медленнее.
Во-первых это три типа синхронизации: biased, thin и fat, а не одна.
biased — самый простой и быстрый тип блокировки, при помощи cas-а (как я помню единственного) биндится к одному и тому же потоку, если он постоянно захватывает монитор. Накладные расходы минимальны. Если в дело вступает другой поток, то тип меняется на следующий
thin — перепривязка монитора происходит уже каждый раз с cas-ом. Происходит до тех пор пока множество потоков не начинает биться за ресурс и дальше мы спускаемся выше, к fat
fat — тут уже используются примитивы ос, что весьма и весьма затратно.
Собственно я думаю я ответил на вопрос почему non-fair* RL часто медленнее стандартного монитора (много оптимизаций со стороны JVM, в то время как RL не трогается)
*fair по своей сути будет в тысячи раз медленнее.
+1
UFO just landed and posted this here
это камент из серии «А я вот ещё про ReentrantLock читал!». Стыдоба.
0
Я вам чем то не угодил? Вашу позицию я понял — кг/ам. Хотите и знаете чем сделать статью лучше и что в ней не правильно — с удовольствием почитаю и исправлю. Не хотите/не знаете — перестаньте, пожалуйста, писать бессмысленные комментарии.
0
1. вообще-то, это было не Вам :) К Вам были конкретные претензии, вполне раскрытые юзером ashofthedream. Кажется, Вы многое поправили, и это правильно.
2. я сам разберусь, что мне писать, а что нет.
2. я сам разберусь, что мне писать, а что нет.
+2
Это было обращено к тому, кто хотел помочь, вместо того чтобы выделываться. Никаких претензий к комментарию aleks_pingvin'a не имею и в плане на статью добавил пометку на ReentrantLock и барьеры. В чем смысл вашего комментария я понять не могу… Унизить? Выпендриться? Или одно другого не исключает?
0
UFO just landed and posted this here
> В частности, в примерах не используется синхронизация
Это сильно, да :)
Вообще в современном мире Java есть гораздо более адекватные способы работы с потоками, их пулами, асинхронным выполнением и прочим. Не в обиду автору — но если кто серьезно собирается «черпать знания» из статьи где автор не понимает зачем volatile нужен в проверке условия выхода из потока, то я таким настоятельно советую поискать более другие источники знаний.
Это сильно, да :)
Вообще в современном мире Java есть гораздо более адекватные способы работы с потоками, их пулами, асинхронным выполнением и прочим. Не в обиду автору — но если кто серьезно собирается «черпать знания» из статьи где автор не понимает зачем volatile нужен в проверке условия выхода из потока, то я таким настоятельно советую поискать более другие источники знаний.
+7
Сильно то, что не используется синхронизация или сильно то, что в фразе не правильный смысл?)
Volatile — добавил. Зачем он нужен — понял. Есть еще замечания?
Да, и я совсем забыл про то, как называл себя в статье великим знатоком многопоточного программирования, несущим знания в народ… хотя подождите, я же этого не писал. Хм, наверное потому что я так не думаю. Вот ведь интересно, с чего все остальные взяли обратнное? Наверное потому же почему люди верят в то, что по телеку вещают только величайшие умы современности, просто не способные ошибаться из-за своей безграничной крутости и приближенности к богу.
Volatile — добавил. Зачем он нужен — понял. Есть еще замечания?
Да, и я совсем забыл про то, как называл себя в статье великим знатоком многопоточного программирования, несущим знания в народ… хотя подождите, я же этого не писал. Хм, наверное потому что я так не думаю. Вот ведь интересно, с чего все остальные взяли обратнное? Наверное потому же почему люди верят в то, что по телеку вещают только величайшие умы современности, просто не способные ошибаться из-за своей безграничной крутости и приближенности к богу.
0
Строго говоря, к автору статьи у меня вопросов нет, и на вопрос " Есть еще замечания?" я не стану повторять многое из того, что критики до меня сообщили. Замечу, что если бы мне на интервью показали такое понимание работы в многопоточной среде, то я бы… не удовлетворился.
Но речь не о том. А речь о том, что я с удивлением обнаружил, что подобного рода статья от ну очень уж «не знатока многопоточного программирования» вызывает живой народный интерес, и прочитав ее он (народ) действительно проникнется странной идеей, что «Наиболее очевидная область применения многопоточности – это программирование интерфейсов». А после этого начнет эту многопоточность в интерфейсы вставлять. Что само по себе очень скользкая область, да и к тому же полностью обойденные вниманием проблемы синхронизации, конфликтов/гонок и вся специфика работы с muttable сущностями в конкурентной среде преподнесут массу неприятных и неожиданных сюрпризов. Ну и не говоря о том, что так, как описано в примерах, на таком уровне ручного управления Threads, в реальной жизни стараются не пользоваться, т.к. есть более адекватные и управляемы средства.
Всем, кому интерсно мое мнение, я советую вдумчиво почитать Java Concurrency in Practice. Там все ясно, доступно и разумно рассказано.
Но речь не о том. А речь о том, что я с удивлением обнаружил, что подобного рода статья от ну очень уж «не знатока многопоточного программирования» вызывает живой народный интерес, и прочитав ее он (народ) действительно проникнется странной идеей, что «Наиболее очевидная область применения многопоточности – это программирование интерфейсов». А после этого начнет эту многопоточность в интерфейсы вставлять. Что само по себе очень скользкая область, да и к тому же полностью обойденные вниманием проблемы синхронизации, конфликтов/гонок и вся специфика работы с muttable сущностями в конкурентной среде преподнесут массу неприятных и неожиданных сюрпризов. Ну и не говоря о том, что так, как описано в примерах, на таком уровне ручного управления Threads, в реальной жизни стараются не пользоваться, т.к. есть более адекватные и управляемы средства.
Всем, кому интерсно мое мнение, я советую вдумчиво почитать Java Concurrency in Practice. Там все ясно, доступно и разумно рассказано.
+1
UFO just landed and posted this here
> интересно зачем потоку самому вызывать этот метод?! Очевидно что когда он живой результат всегда false
А вот тут Вы сильно ошибаетесь, interrupted — это просто флаг. Поток может быть живым, а interrupted == true. Обычно этот флаг устанавливают из другого потока в целях уведомить данный поток о чём-то, например, что пора завершаться. А в самом потоке Вы уже проверяете этот флаг в нужном месте (или просто ловите исключение) и корректно завершаете работу. Но теоретически можно использовать этот флаг и в других целях.
А вот тут Вы сильно ошибаетесь, interrupted — это просто флаг. Поток может быть живым, а interrupted == true. Обычно этот флаг устанавливают из другого потока в целях уведомить данный поток о чём-то, например, что пора завершаться. А в самом потоке Вы уже проверяете этот флаг в нужном месте (или просто ловите исключение) и корректно завершаете работу. Но теоретически можно использовать этот флаг и в других целях.
+1
… ну ладно по быстрому: notify() — ничего не сказано, для sleep() — это тоже самое что для минуса плюс. Кстати и про yield() забыли.
Насколько я знаю notify() работает в паре с wait(), а не с sleep().
Про yield() написал, спасибо.
Про сокеты убрал, пример, и правда, не удачный.
Объяснение про процессы много места не заняло. Оно дано для общей информации и без особого смысла. Без него параграф про процессы был бы суховатым.
Неточность в фразе про создание процесса исправил, еще раз спасибо.
Префикс «m» в имени переменной значит «member», а именно — член класса. Этот префикс служит для отличения переменных класса от переменных метода, в которых префикс не указывается. Вероятно вы подумали что он значит «my»…
Исправил текст про предугадание выполнения программы.
Насчет interrupted() я не очень понял. Именно этот метод вызавается потоком для проверки того, прерван он или нет. Метод interrupt() не убивает поток, а выставляет флаг прерывания, который потом проверяется методом interrupted().
Предложение в параграфе приоритета потоков убрал.
0
UFO just landed and posted this here
Для пущего укорочения кода
Можно еще более укоротить код использовав анонимный внутренний класс
public class Program //Класс с методом main().
{
public static void main(String[] args)
{
//Создание и Запуск потока
new Thread(new Runnable()
{
public void run() //Этот метод будет выполняться в побочном потоке
{
System.out.println("Привет из побочного потока!");
}
}).start();
System.out.println("Главный поток завершён...");
}
}
0
Спасибо, самое то для начинающих.
PS Ну и где же следующая статья про синхронизацию? :)
PS Ну и где же следующая статья про синхронизацию? :)
0
Sign up to leave a comment.
Articles
Change theme settings
Многопоточность в Java