Ответы пользователя по тегу Многопоточность
  • Алгоритм многопоточности?

    @nirvimel
    Не надо создавать отдельный поток для каждого файла. Создайте два пула потоков.

    Пул №1 (вычислительный): количество потоков равно количеству ядер CPU. Во входную очередь сыплются блоки данных, для которых потоки пула рассчитывают хеши.

    Пул №2 (синхронное чтение с диска): количество потоков равно количеству ядер, помноженному на некоторую константу (в исходниках разных библиотек я видел значения от 2 до 10). Во входную очередь сыплются имена файлов, которые потоки пула открывают, читают и засылают прочитанные блоки во входную очередь пула №1.
    Примечание: расход памяти регулируется ограничением максимальной длинны входной очереди пула № 1. Практически получается, что пул №1 ограничивает нагрузку на пул №2, который в норме недонагружен.

    Отдельный поток, который совершает обход дерева каталогов и засылает найденные имена файлов во входную очередь пула №2. Длину этой очереди, тоже можно ограничить, но не так жестко (я бы задал размер в несколько сотен).

    P.S.: Все очереди с ограничением длины должны быть, конечно же, с блокировками (не lock-free), так как через них происходит регулировка нагрузки (иначе все потоки нагрузятся на 100%).
    Размер блоков данных, поступающих на вход пула №1 не надо делать слишком маленьким (я бы задал 64 килобайта, например).
    Ответ написан
    Комментировать
  • Как поубивать потоки которые я сам же и насоздавал?

    @nirvimel
    В цикле проверяется флаг (условие выхода), изначально заданный в False, но сбрасываемый в True обработчиком команды /kill. Удобно использовать dict для соотнесения отдельным потокам флагов выхода.
    Ответ написан
  • Как считать сериализованные объекты из в файла в ArrayList из этих самых объектов?

    @nirvimel
    Читать объекты в бесконечном цикле до тех пор, пока не вылетит EOFException.
    Ответ написан
    Комментировать
  • Обработка потоков на сервере мессенджера?

    @nirvimel
    Количество потоков не равно количеству открытых сокетов. Расходовать на каждое подключение отдельный поток ни в коем случае нельзя. Но синхронно закрывать сокет после обработки подключения совсем не обязательно. Сокет - просто значение ячейки массива (или карты) будет взято и использовано когда понадобится в любом потоке (работа с конкретным сокетом, конечно, должна быть обернута в соответствующий синхроблок). Единственно, о чем не следует забывать это - KeepAlive пинги (отдельный пул потоков и таймера под них, например), которые обеспечивают сразу две задачи: 1) помогают удержать неактивное соединение (умные роутеры любят закрывать "мертвые" соединения, и клиент, в зависимости от реализации, может делать то же). 2) очищают список сокетов от реально мертвых.
    Ответ написан
    2 комментария
  • Выбор языка для многопоточного приложения под linux?

    @nirvimel
    C - Плюсы: Возможность выжать максимальную скорость из железа.
    Минусы: При переходе с динамических скриптов (типа, упомянутого в вопросе, PHP) может несколько шокировать своей многословностью и необходимостью явно описывать каждую мелочь, которая в других языках выводится неявно.
    Java - Плюсы: Автоматическая сборка мусора сильно облегчает жизнь и смягчает шок при переходе с динамических скриптов. Гениальный JIT - позволяет сократить отставание от голого железа в скорости (в лучшем случае) до 30%-50% (по сравнению с отставанием в разы и десятки раз для динамических скриптов).
    Минусы: Чтобы воспользоваться всей мощью JIT, требуется глубокое понимание принципов его работы и отказ от использования объектов (основной фишки Java) в глубине самых нагруженных циклов.
    C++ - Разные люди по-разному используют его. Кто-то на нем пишет в стиле C, получает быстродействие чистого C и презрение истинных C++совцев. Кто-то на нем пишет в стиле Java и получает более компактный код, но и быстродействие как у Java. На самом деле на этом языке можно писать красивые, элегантные и не уступающие в быстродействии программы, но на это уйдут годы обучения (речь не о синтаксисе языка и не о стандартной библиотеке).
    Ответ написан
    3 комментария
  • Как перезапустить один поток в консоли?

    @nirvimel
    Какие инструменты вы имеете в виду? Снаружи невозможно повлиять на ход выполнения программы. Обработка исключительных ситуаций должна быть предусмотрена в коде. Обычно для этого реализуют что-то типа планировщика (scheduler) в отдельном потоке, который регулярно опрашивает рабочие потоки потоки (worker) и если worker не успел ответить на запрос в течении определенного времени, он убивается и перезапускается. Общение между потоками идет через очереди ConcurrentLinkedQueue (иногда BlockingQueue, но обычно они используются не для опроса, а для пересылки потоков данных). worker в цикле опрашивает входящую очередь и отвечает на пинг через исходящую. Также неплохо завернуть весь worker в обработчик RuntimeException, в котором сигнализировать scheduler о произошедшим.
    Ответ написан
    3 комментария
  • Многопоточное программирвоание java, существуют ли книги?

    @nirvimel
    Многопоточность неплохо рассмотрена у Брюса Эккеля, например.
    Если интересует средства стандартной библиотеки (классический подход к многопоточности) - то 100 страниц вполне достаточно, я считаю.
    Если интересуют альтернативные подходы, типа акторов, promise/future и stm, то для этого существую отдельные библиотеки. У каждой библиотеки есть своя документация, книги также пишутся по конкретным библиотекам, при этом не говорят словами "многопоточность под java", а называют конкретную библиотеку.

    Еще один сравнительный обзор различных книг по многопоточности в java. Но лично я не читал ни одной из них, простое чтение исходников стандартной библиотеки (прекрасно документированной) плюс обще пониманием архитектуры аппаратной платформы и виртуальной машины, дает наилучший результат на практике.
    Ответ написан
    Комментировать
  • Как получить данные из потоков обратно в main в java?

    @nirvimel
    Для этого существует очередь LinkedBlockingQueue.
    Потоки пишут в нее возвращаемые значения, промаркированные id задания.
    main читает из нее и восстанавливает массив возвращаемых значений по их id, не опираясь на порядок элементов в очереди, который ничем не гарантирован.
    Ответ написан
    Комментировать
  • Как организовать параллельную работу по сети с несколькими устройствами?

    @nirvimel
    1. Подобные сервера лучше писать не на потоках threading (которые все равно упираются в GIL), а на "зеленых" потоках, например gevent, который создан для решения задач, подобной вашей, с максимальной производительностью.
    2. Проблему зависания потоков в вечном ожидании решает настройка keepalive: клиент обязуется передавать пустые пакеты раз в n секунд, если ему больше нечего передавать. А сервер делает socket.settimeout(n+10) и при вызове recv отлавливает исключение socket.timeout, которое сигнализирует, что клиент "отвалился".
    Ответ написан
    Комментировать
  • Почему создаются дополнительные потоки в конце очереди?

    @nirvimel
    С виду тут все в полном порядке.
    Имеем 50 ПАРАЛЛЕЛЬНЫХ потоков, которые питаются из очереди в 500 элементов.
    1. К моменту когда первый поток окончил выполнение своего задания, на выполнение которого потратил некоторое время, в очереди давно уже осталось 450 элементов, ведь расхватывают новые задания потоки мгновенно и ПАРАЛЛЕЛЬНО.
    2. К моменту, когда завершилось выполнение 450-го задания, оставшиеся 50 уже находятся в работе, их уже расхватали потоки, и в очереди осталось 0 элементов. После чего оставшиеся 49 потоков заканчивают выполнение своих заданий и каждый рапортует о том, что наблюдает в очереди ноль элементов, после чего воркеры вылетают по task_done() и подбираются join-ом в основном потоке.
    Ответ написан
    2 комментария