Темы часто участвуют в работе. Например, некоторые задачи часто передаются потокам для асинхронного выполнения. Или программа сервера устанавливает отдельную задачу обработки потока для каждого запроса. За пределами потоков, таких как подключение к базе данных, которое мы используем. Эти операции создания, разрушения или открытия и закрытия оказывают большое влияние на производительность системы. Следовательно, использование «пула» выделено.
1. Зачем использовать пул потоков
В реализации, описанной в разделе 3.6.1, каждому клиенту назначается новый рабочий поток. Когда работник поток общается с клиентом, поток уничтожается. Этот метод реализации имеет следующие недостатки:
• Накладные расходы создания и разрушения сервера (включая время и системные ресурсы) очень высоки. Этот элемент не должен быть объяснен, вы можете проверить «процесс создания потока». В дополнение к работе, выполненной самой машиной, нам также необходимо создать экземпляр и запустить, что требует занятости ресурсов стека.
• В дополнение к накладным расходам создания и уничтожения потоков, активные потоки также потребляют системные ресурсы. Это должно быть потребление ресурсов стека. Также считается угадать количество подключений к базе данных.
• Если количество потоков исправлено, и каждый поток имеет длинный цикл объявления, то переключение потока также является относительно фиксированным. Различные операционные системы имеют разные циклы переключения, обычно около 20 мс. Упомянутый здесь переключатель предназначен для передачи прав на использование ЦП между потоками в соответствии с планированием JVM и базовой операционной системой. Если потоки часто создаются и уничтожаются, потоки будут часто переключаться, потому что после уничтожения потока право на использование должно быть передано в подготовительный поток, чтобы поток мог получить шанс запустить. В этом случае переключение между потоками не следует за фиксированным циклом переключения системы, а накладные расходы переключающих потоков даже больше, чем накладные расходы на создание и разрушение.
Относительно говоря, используя пулы потоков, некоторые потоки предварительно созданы, которые постоянно удаляют задачи из рабочей очереди, а затем выполняют задачу. Когда работник поток выполняет одну задачу, он продолжает выполнять другую задачу в очереди работы. Преимущества следующие:
• Уменьшает количество создания и разрушения, и каждый рабочий поток может быть повторно использован все время и может выполнять несколько задач.
• Количество потоков в пуле потоков может быть легко скорректировано в соответствии с пропускной способностью системы, чтобы предотвратить сбои системы из -за чрезмерных системных ресурсов.
2. Простая реализация пула потоков
Ниже приведен простой пул потоков, написанный мной, который также был непосредственно взят из книги программирования сети Java.
Поток пакетов; импортировать java.util.linkedlist;/*** Реализация пула потоков, основанная на длине, максимальной длине и длине очереди обычного пула потоков, мы можем увеличить количество реализаций* @author han*/public class mythreadpool extends extgroup {// cpu Number ---- runtime.getruntime (). //Ть закрыть личный логический isclosed = false; // очередь частный LinkedList <Runnable> workqueue; // идентификатор бассейна потоков Private Static Int ThreadpoolId; private int threadid; public mythreadpool (int poolsize) {super ("mythreadpool."+threadpoolid); ThreadPoolId ++; SetDaemon (True); workqueue = new LinkedList <Runnable> (); for (int i = 0; i <poolsize; i ++) {new WorkThread (). start (); }} // Здесь вы можете перейти на ConcurrentLinkedQueue, чтобы избежать эффективности использования синхронизированного общедоступного синхронизированного void execute (runnable task) {if (isclosed) {бросить new allodalstateexception («Пул соединений был закрыт ...»); } else {workqueue.add (task); notify (); }} Защищенный синхронизированный runnable getTask () бросает прерывания, {while (workqueue.size () == 0) {if (isclosed) {return null; } ждать(); } return workqueue.removefirst (); } public synchronized void close () {if (! isclosed) {isclosed = true; rabqueue.clear (); прерывать(); }} public void join () {synchronized (this) {isClosed = true; notifyAll (); } Thread [] Threads = новый поток [activeCount ()]; int count = перечислять (потоки); for (int i = 0; i <count; i ++) {try {threads [i] .join (); } catch (Exception e) {}}} класс expertends extends {public workThread () {super (mythreadpool.this, "horkthread"+(thinkid ++)); System.out.println ("create ..."); } @Override public void run () {while (! IsErengreting ()) {System.out.println ("run .."); Выполняемая задача = null; try {// Это метод блокировки задачи = getTask (); } catch (Exception e) {} if (task! = null) {task.run (); } else {break; }}}}}}Этот пул потоков в основном определяет рабочую очередь и несколько предварительно созданных потоков. Пока вызов метод выполнения, вы можете отправить задачи в поток.
Когда нет задачи, последующий поток будет блокировать в getTask () до тех пор, пока не появится новая задача и не будет пробуждена.
Как соединение, так и закрытие могут быть использованы для закрытия бассейна резьбов. Разница в том, что JOIN выполнит задачи в очереди, в то время как Close сразу же очистит очередь и прертит все потоки работников. Enterrupt () in blode () эквивалентен вызова соответствующего прерывания (), содержащего дочерние потоки в потоке. Следовательно, когда поток ждет или спит, будет брошено нарушение.
Тестовый класс выглядит следующим образом:
открытый класс testmyThreadpool {public static void main (string [] args) бросает прерывания {mythreadpool pool = new Mythreadpool (3); for (int i = 0; i <10; i ++) {pool.execute (new runnable () {@override public void run () {try {thread.sleep (1000);} catch (прерывание Exception e) {} system.out.println ("working ...");}}); } pool.join (); //pool.close (); }}3. Пул потоков, предоставленный библиотекой классов JDK
Java обеспечивает хорошую реализацию пула потоков, которая является более надежной и эффективной, чем наша собственная реализация, а также имеет более мощные функции.
Схема классов выглядит следующим образом:
Пожилые люди уже дали хорошее объяснение об этом типе пула потоков. Любой пул ниток Java под Baidu имеет очень подробные примеры и написанные учебные пособия, поэтому я не буду повторять их здесь.
4. Бассейн с нитью впресс -инъекции
При использовании Spring Framework, если мы используем методы, предоставленные Java для создания пула потоков, очень неудобно управлять в многопоточных приложениях и не соответствует нашей идее использования Spring. (Хотя пружина может быть введена статическими методами)
Фактически, сама весна также обеспечивает хорошую реализацию пулов потоков. Этот класс называется Threadpooltaskexecutor.
Конфигурация в пружине выглядит следующим образом:
<bean id = "experationservice"> <name = "corepoolsize" value = "$ {threadpool.corePoolsize}" /> <!-Минимальное количество потоков, поддерживаемых пулом потоков-> <свойство = "KeepAliveseconds" value = "$ {treadpool.keepaliveseconds}" /> <! name = "maxpoolsize" value = "$ {threadpool.maxpoolsize}" /> <!-Максимальное количество потоков, поддерживаемых пулом потоков-> <name = "Queuecapacity" value = "$ {Threadpool.QueCapacity}" /> <!5. Примечания об использовании пулов потоков
• тупик
Любая многопоточная программа имеет риск смертоносного значения. Самым простым случаем является то, что два потока AB, A Holds Lock 1, запрос Lock 2, B содержит Lock 2 и запрос Lock 1. (Эта ситуация также будет отображаться в Exclusive Lock MySQL, и база данных будет напрямую сообщать о сообщении об ошибке). В пуле потоков есть еще один тупик: предполагая, что все рабочие потоки в пуле потоков заблокированы при выполнении своих соответствующих задач, и они ждут результата выполнения определенной задачи A. Задача A находится в очереди и не может быть выполнена, потому что нет холостых потоков. Таким образом, все ресурсы пула потоков будут заблокированы, и будут сгенерированы тупики.
• Недостаточно системных ресурсов
Если количество потоков в пуле потоков очень большое, эти потоки будут потреблять большое количество ресурсов, включая память и другие системные ресурсы, которые серьезно влияют на производительность системы.
• Одновременная ошибка
Рабочая очередь пула потоков зависит от методов wait () и уведомления (), чтобы работники могли своевременно получать задачи, но эти два метода трудно использовать. Если код неверен, уведомления могут быть потеряны, в результате чего рабочая потока оставалась холодной, игнорируя задачи, которые необходимо обрабатывать в очереди на работу. Потому что лучше всего использовать более зрелые бассейны потоков.
• Утечка потока
Серьезным риском использования пулов потоков является утечка потоков. Для пулов потоков с фиксированным количеством рабочих потоков, если поток работников бросает Runtimeexception или ошибку при выполнении задачи, и эти исключения или ошибки не пойманы, поток работника заканчивается ненормально, в результате чего пул потоков постоянно теряет поток. (Это так интересно)
Другая ситуация заключается в том, что рабочая поток заблокирован при выполнении задачи. Если он ждет входных данных пользователя, но пользователь не вводит данные, в результате чего поток блокируется все время. Такой рабочий поток только по имени, и на самом деле он не выполняет никаких задач. Если все потоки в пуле потоков находятся в этом состоянии, пул потоков не может добавить новые задачи.
• перегрузка задачи
Когда в очереди труда работника выполняется большое количество задач, которые были выполнены в очереди работников, эти задачи сами могут потреблять слишком много системных ресурсов и вызвать нехватку ресурсов.
Подводя итог, при использовании пулов потоков следует соблюдать следующие принципы:
1. Если задача A должна ждать результата выполнения задачи B синхронно во время выполнения, то задача A не подходит для добавления в очередь работы пула потоков. Если вам нужно ждать, пока другие задачи выполнят результаты, такие как задача A, чтобы быть добавленной в очередь, это может вызвать тупик
2. Если задача может быть заблокирована и блокирована в течение длительного времени, время ожидания должно быть установлено, чтобы избежать постоянного блокировки рабочей потока и вызывая утечку потока. В программе сервера, когда поток ждет, пока клиент подключится или ждал данных, отправленных клиентом, это может вызвать блокировку. Вы можете установить время следующими способами:
Вызовите метод SetSotimeout Serversocket, чтобы установить время ожидания, чтобы подождать, пока клиент подключится.
Для каждого сокета, подключенного к клиенту, вызовите метод SetSotimeout Socket, чтобы установить время ожидания, ожидая, когда клиент отправит данные.
3. Понять характеристики задачи и проанализировать, выполняет ли задача операции, которые часто блокируют операции ввода -вывода, или выполняют операции, которые не будут блокировать. Первый занимает процессор времени периодически, в то время как последний имеет более высокий уровень использования. Сколько времени нужно, чтобы выполнить задачу? Это краткосрочная задача или долгосрочная задача? Затем классифицируйте задачи в соответствии с характеристиками задачи, а затем добавьте различные типы задач в очередь работы разных пулов потоков. Таким образом, каждый пул потоков может быть выделен и скорректирован в соответствии с характеристиками задачи.
4. Изменить размер бассейна. Оптимальный размер пула резьбов в основном зависит от количества доступных процессоров в системе и характеристик задач в очереди в работе. Если в системе с n процессорами есть только одна очередь работы, и все они представляют собой задачи с арифметической природой (не блокирующая), то, когда пул потоков имеет n или n+1 рабочие потоки, обычно будет получено максимальное использование ЦП.
Если очередь работы содержит задачи, которые выполняют операции ввода -вывода и часто блокируют, размер пула потоков превышает количество доступных процессоров, потому что не все рабочие потоки работают все время. Выберите типичную задачу, а затем оцените соотношение времени ожидания до времени, которое фактически занимает ЦП для выполнения операций в проекте, который выполняет эту задачу. Для системы с N -процессорами необходимо установить примерно n*(1+WT/ST) потоки, чтобы обеспечить полное использование ЦП.
Конечно, использование ЦП - не единственное, что нужно учитывать в процессе настройки пулов потоков. По мере увеличения количества работ пула потоков также будут происходить ограничения памяти или другие ресурсы, такие как сокеты, открытые ручки или подключения к базе данных и т. Д. Для обеспечения того, чтобы системные ресурсы, потребляемые многопользовательными, находятся в рамках выносливости системы.
5. Избегайте перегрузки задач. Сервер должен ограничить количество параллельных соединений клиентов на основе способности системы. Когда соединение клиента превышает предельное значение, сервер может отклонить соединение и сделать дружеские подсказки или ограничить длину очереди.
Вышеуказанные несколько методов реализации и ответов на пулы потоков Java - это все контент, которым я поделился с вами. Я надеюсь, что вы можете дать вам ссылку, и я надеюсь, что вы сможете поддержать Wulin.com больше.