Что такое Java MultiThreading
Java предоставляет механизм для выполнения нескольких задач одновременно (одновременно и независимо). Несколько потоков сосуществуют в одном и том же процессе JVM, поэтому они имеют одно и то же пространство памяти. По сравнению с несколькими процессами связь между несколькими потоками легче. Насколько я понимаю, многопоточное многопользовательское управление Java полностью для улучшения использования процессора. В темах Java есть 4 состояния: новые, бегущие, заблокированные и мертвые. Ключ блокирует. Блокировка означает ожидание. Блокирующая нить не участвует в распределении среза по времени диспетчера потока, поэтому, естественно, он не будет использовать процессор. В многопоточной среде эти не заблокированные потоки работают и в полной мере используют процессор.
Резюме из 40 вопросов
1. Что такое многопоточное?
Вопрос, который может показаться бессмысленным для многих людей: я могу просто использовать многопоточное, но что такое использование? На мой взгляд, этот ответ еще более глупо. Так называемое «знание того, что правда»,-это «знание того, что является правдой», «зная, что правда», «зачем использовать»-это «знание того, что правда». Только достигнув уровня «знания того, что является правдой», можно сказать, что можно свободно применять точку знания. Хорошо, позвольте мне рассказать вам, что я думаю об этой проблеме:
(1) Получить полную игру для преимуществ многоядерного процессора
С развитием промышленности сегодняшние ноутбуки, настольные компьютеры и даже коммерческие серверы приложений-все это двухъядерные, а 4-яловые, 8-ядерные или даже 16-ядерные не редкость. Если это программа с одним набором, 50% потрачено в течение двухъядерного процессора, а 75% потрачены впустую на 4-ядерном процессоре. Так называемый «многопоточный» на одноядерном процессоре представляет собой фальшивое многопоточное. Процессор будет обрабатывать только кусок логики одновременно, но потоки переключаются относительно быстро, что выглядит так, как будто несколько потоков работают «одновременно». Многопользовательская чтения на многоядерных процессорах-это настоящая многопоточная. Это может позволить вашей многосегментной логике работать одновременно и многопоточно. Это может по-настоящему дать полную игру для преимуществ многоядерных процессоров для достижения цели полного использования ЦП.
(2) предотвратить блокировку
С точки зрения эффективности работы программ, одноядерный процессор не только не даст полной игры для преимуществ многопользовательского, но и снизить общую эффективность программы, поскольку запуск многопользования на одноядном процессоре приведет к переключению контекста потоков, что снизит общую эффективность программы. Тем не менее, нам все еще нужно применить многопоточное честь на одноядерные процессоры для предотвращения блокировки. Представьте себе, что если одноядерный процессор использует один поток, если поток блокируется, например, удаленно чтение определенных данных, то одноранговое одно время не возвращалось и не устанавливает время ожидания, тогда вся ваша программа прекратится до возврата данных. Многопользовательское управление может предотвратить эту проблему. Несколько потоков работают одновременно. Даже если код одного потока заблокирован от чтения данных, он не повлияет на выполнение других задач.
(3) Легко моделировать
Это еще одно преимущество, которое не так очевидно. Предположим, что существует большая задача A, однопоточное программирование, тогда вам нужно много рассмотреть, и для создания всей модели программы более трудно. Однако, если вы сломаете эту большую задачу A на несколько небольших задач, задачу B, задача C и задача D, создайте программу по отдельности и выполните эти задачи отдельно через несколько потоков, она будет намного проще.
2. Как создать потоки
Более распространенная проблема, как правило, две:
(1) Унаследовать класс потоков
(2) Реализуйте запускаемый интерфейс
Что касается того, для которого лучше, само собой разумеется, что последнее определенно лучше, потому что способ реализации интерфейсов более гибкий, чем метод класса наследования, а также может уменьшить связь между программами. Программирование, ориентированное на интерфейс, также является ядром шести основных принципов дизайна.
3. Разница между методом start () и методом run ()
Только когда будет называется метод start (), будут отображаться характеристики мультипотчика, а код в методе run () различных потоков будет выполнен попеременно. Если вы просто вызовите метод run (), код будет выполнен синхронно. Вы должны ждать кода в методе run () одного потока, который будет выполнен, прежде чем другой поток сможет выполнить код в своем методе run ().
4. Разница между выполняемым интерфейсом и каллируемым интерфейсом
Есть немного глубокого вопроса, и он также показывает широту знаний, изученных программистом Java.
Возвращаемое значение метода run () в интерфейсе Runnable void, и он просто выполняет код в методе run (); Метод Call () в интерфейсе Callable имеет возвратное значение, которое является общим, и может использоваться для получения результатов асинхронного выполнения в сочетании с будущим и FutureTask.
Это на самом деле очень полезная функция, потому что основная причина, по которой многопоточное чтение сложнее и сложнее, чем отдельные потоки, заключается в том, что многопоточное чтение полна неизвестных. Был ли определенный поток? Как долго была выполнена поток? Данные, которые мы ожидаем, когда выполняется поток? Не знает, что все, что мы можем сделать, это ждать выполнения этой многопоточной задачи. Callable+Future/FutureTask может получить результаты многопоточного запуска и может отменить задачу потока, когда время ожидания слишком длинное и требуемые данные не получены. Это действительно полезно.
5. Разница между циклическим барьером и Countdownlatch
Оба класса, которые выглядят немного похожими, могут быть использованы, чтобы указать, что код работает в определенной точке под java.util.concurrent. Разница между ними состоит в:
(1) После того, как резьба циклического барьера работает в определенную точку, нить прекращается. Пока все потоки не достигнут этой точки, все потоки не будут работать снова; Countdownlatch нет. После того, как поток работает в определенную точку, он просто дает определенное значение -1, и поток продолжает работать.
(2) Cyclicbarrier может вызвать только одну задачу, Countdownlatch может вызвать несколько задач
(3) Cyclicbarrier может быть использован повторно, Countdownlatch не может быть повторно используется, а значение счета равно 0 не будет использоваться повторно, а Countdownlatch не будет использоваться снова
6. Роль нестабильных ключевых слов
Очень важная проблема заключается в том, что каждый Java-программист, который изучает и применяет многопоточное, должен освоить его. Предварительным условием для понимания роли летучего ключевого слова является понимание модели памяти Java. Я не буду говорить о модели памяти Java здесь. Вы можете обратиться к точке 31. Есть две основные функции летучих ключевых слов:
(1) Многопользовательская прочтения в основном вращается вокруг двух характеристик видимости и атомальности. Переменные, модифицированные летучим ключевым словом, гарантируют их видимость между несколькими потоками, то есть каждый раз, когда летучая переменная читается, это должны быть последние данные.
(2) Основное выполнение кода не так просто, как язык высокого уровня, который мы видим - программы Java. Его выполнение -код Java -> ByteCode -> Выполнить соответствующий код C/C ++ в соответствии с кодом ByteCode -> C/C ++, скомпилируется в язык сборки -> взаимодействие с аппаратной схемой. В действительности, чтобы получить лучшую производительность, JVM может переупорядочить инструкции, и некоторые неожиданные проблемы могут возникнуть при многопоточной. Использование летучего будет запретить семантическое повторное заказа, что, конечно, в определенной степени снижает эффективность выполнения кода
С практической точки зрения важной ролью летучих является объединение с CAS для обеспечения атомичности. Для получения подробной информации вы можете обратиться к классам в рамках пакета java.util.concurrent.atomic, например, Atomicinteger.
7. Что такое безопасность потока
Еще один теоретический вопрос, есть много ответов. Я хотел бы дать тот, который, как я лично считаю, является лучшим объяснением: если ваш код всегда может получить тот же результат при выполнении при многопоточной чтении и однопользовании, то ваш код безопасен для поток.
Есть что -то, что стоит упомянуть об этой проблеме, то есть есть несколько уровней безопасности потоков:
(1) Неизвественно
Как строка, целое число, длинное и т. Д., Все они являются окончательными типами. Ни один поток не может изменить их значения. Если вы хотите их изменить, вы не будете создавать новый. Следовательно, эти неизменные объекты могут быть использованы непосредственно в многопоточной среде без каких-либо средств синхронизации.
(2) Абсолютная безопасность резьбы
Независимо от среды выполнения, абоненту не нужны дополнительные меры синхронизации. Для этого вам обычно приходится оплачивать много дополнительных затрат. В Java это на самом деле не безопасные для тему классы. Тем не менее, есть также классы, которые абсолютно безопасны для потока, такие как CopeonWritearRaylist и CopyonWritearRaySet
(3) Относительная безопасность резьбы
Относительная безопасность потока - это то, что мы обычно называем безопасностью потока. Например, вектор, добавление и удаление методов являются атомными операциями и не будут прерваны, но это ограничено этим. Если поток, пересекающий определенный вектор, одновременно добавляется поток, то одноразовое экспресс будет происходить в 99% случаев, что является ошибочным механизмом.
(4) Поток небезопасно
Об этом нечего сказать. ArrayList, LinkedList, HashMap и т. Д.-все это нетребованные классы.
8. Как получить файл дампы потока в Java
Для таких проблем, как Dead Loop, Deadlock, блокировка, медленное открытие страницы и т. Д., Нажатие на дамп потока - лучший способ решить проблему. Так называемый дамп потока-это стек резьбы. Есть два шага для получения стека потоков:
(1) Получите PID потока, вы можете использовать команду JPS, и вы также можете использовать PS -EF | grep java в среде Linux
(2) Распечатайте стек потоков, вы можете использовать команду JStack PID, и вы также можете использовать PIL -3 PID в среде Linux
Кроме того, класс потоков предоставляет метод getStackTrace (), который также можно использовать для получения стека потоков. Это метод экземпляра, поэтому этот метод связан с конкретным экземпляром потока. Каждый раз, когда вы получаете стек, который в настоящее время работает в определенном потоке.
9. Что произойдет, если у потока есть исключение времени выполнения?
Если это исключение не пойман, поток перестанет выполнять. Другой важный момент: если этот поток содержит монитор определенного объекта, монитор объекта будет немедленно выпущен
10. Как поделиться данными между двумя потоками
Просто делитесь объектами между потоками, а затем вызовите и подождите через ожидание/уведомление/уведомление, wait/signal/signalall. Например, блокировка блокировки очереди предназначена для обмена данными между потоками.
11. В чем разница между методом сна и методом ожидания
Этот вопрос часто задают, как метод сна, так и метод ожидания могут использоваться для отказа от ЦП в течение определенного периода времени. Разница в том, что если поток содержит монитор объекта, метод сна не отказатся от монитора этого объекта, а метод ожидания отказатся от монитора этого объекта.
12. Какова роль модели потребительской модели производителя?
Этот вопрос теоретический, но важен:
(1) Повысить эффективность работы всей системы за счет балансировки производственных мощностей производителей и потребителей, что является наиболее важной ролью производителя потребительской модели.
(2) Разъединение, это функция, сопровождаемая моделью производителя и потребителя. Развязка означает, что между производителями и потребителями меньше связей. Чем меньше соединений, тем больше они могут разрабатывать самостоятельно, не получая взаимных ограничений.
13. Что такое использование нитолокальных
Проще говоря, Threadlocal - это практика обмена пространством на время. Каждый поток поддерживает Threadlocal.THREADLOCALMAP, реализованный методом открытого адреса для выделения данных и не совместно использует данные, поэтому, естественно, не будут никаких проблем безопасности потоков.
14. Зачем WAIT () и notify ()/notifyall () методы будут вызоваться в блоке синхронизации
Это навязывается JDK. Метод wait () и notify ()/notifyall () должен сначала получить блокировку объекта перед вызовом
15. В чем разница между методом wait () и методом notify ()/notifyall () при отказе от монитора объекта
Разница между методом wait () и методом notify ()/notifyall () при отказа от монитора объекта заключается в том, что метод wait () немедленно освобождает монитор объекта, в то время как метод notify ()/notifyall () будет ждать оставшегося кода поток, прежде чем отказаться от монитора объекта.
16. Зачем использовать пул потоков
Избегайте частого создания и разрушения потоков для достижения повторного использования объектов потока. Кроме того, использование пулов потоков также может гибко контролировать количество параллелизма в соответствии с проектом.
17. Как определить, удерживает ли поток монитор объекта
Я также видел многопоточный вопрос интервью в Интернете, чтобы узнать, что существует способ определить, содержит ли поток монитор объекта: класс потоков предоставляет метод Holdslock (Object obj), который вернет True, если и только тогда, когда монитор объекта OBJ хранится потоком. Обратите внимание, что это статический метод, который означает, что «определенный поток» относится к текущему потоку.
18. Разница между синхронизированным и повторным залогом
Синхронизированный является тем же ключевым словом, как будто, иначе, для и пока, а Reentrantlock - это класс, который является важной разницей между ними. Поскольку Reentrantlock является классом, он обеспечивает все больше и больше гибких функций, чем синхронизированные, которые можно наследовать, иметь методы и иметь различные классовые переменные. Масштабируемость повторного залога, чем синхронизированный, отражается в нескольких точках:
(1) Reentrantlock может установить время ожидания для получения замка, избегая тупика
(2) Reentrantlock может получить различную информацию о блокировке
(3) Reentrantlock может гибко реализовать многоканальное уведомление
Кроме того, блокирующие механизмы двух на самом деле разные. Базовый метод перезагрузки небезопасного парка для блокировки, и синхронизированная операция должна быть известным словом в заголовке объекта, я не могу в этом быть уверен в этом.
19. Какова параллелизм concurrenthashmap
Согласно параллельности concurrenthashmap - это размер сегмента, который по умолчанию составляет 16, что означает, что не более 16 потоков могут работать одновременно concurrenthashmap. Это также самое большое преимущество concurrenthashmap на хэштебе. В любом случае, может одновременно иметь две потоки, получая данные в хэштебе?
20. Что такое readwritelock
Прежде всего, давайте проясним, что не то, что Reentrantlock не очень хорош, просто в некоторых случаях Reenterlock ограничен. Если используется Reentrantlock, может быть предотвращение несоответствий данных, вызванных потоком данных, и данных чтения потока B. Тем не менее, таким образом, если данные по чтению C и поток D также читают данные, чтение данных не изменит данные. Нет необходимости блокировать его, но он все еще блокирует его, что снижает производительность программы.
Из-за этого родился чтение блокировки. ReadWritelock-это интерфейс блокировки чтения-записи. ReentrantreadWritelock - это конкретная реализация интерфейса ReadWritelock, которая осознает разделение чтения и записи. Читать блокировки обмениваются, а блокировки записи эксклюзивны. Чтение и чтение и чтение не будет взаимоисключающим. Только чтение и запись, писать и читать, записать и записать, будет взаимоисключающим, улучшая производительность чтения и записи.
21. Что такое FutureTask
Это фактически упоминается ранее. FutureTask представляет собой асинхронную операцию задачи. Конкретный класс реализации Callable может быть передан в FutureTask, который может ждать результата этой асинхронной операции, чтобы получить, определить, была ли она завершена, и отменить задачу. Конечно, поскольку FutureTask также является классом реализации запускаемого интерфейса, FutureTask также может быть размещен в пуле потоков.
22. Как найти, какой поток использует самый длинный процессор в среде Linux
Это более практическая проблема, и я думаю, что эта проблема весьма значима. Вы можете сделать это:
(1) Получите PID, JPS или PS -FID проекта | grep java, который упоминался ранее
(2) Top -h -p PID, порядок не может быть изменен
Это распечатает процент времени процессора, которое текущий проект берет для каждого потока. Обратите внимание, что здесь является LWP, который является номером потока нативного потока операционной системы. My Notebook Mountain не развертывает Java Projects в среде Linux, поэтому невозможно сделать скриншоты и демонстрации. Если компания развертывает проект с использованием среды Linux, вы можете попробовать его.
Использование "Top -h -p Pid" + "JPS PID" может легко найти стек резьбов, который занимает высокий процессор, тем самым позиционируя причину занятости высокого процессора, что, как правило, связано с неправильными операциями кода, которые приводят к мертвому циклу.
Наконец, позвольте мне упомянуть, что LWP, сыгранный с «Top -H -P Pid», является десятичным, а местный номер ветки, сыгранный с «JPS PID», является шестнадцатеричным. После преобразования вы можете найти текущий стек резьбов, который занимает высокий процессор.
23. Java Programming Напишите программу, которая вызовет тупик
Я впервые увидел этот вопрос и подумал, что это очень хороший вопрос. Многие люди знают, что такое тупик: нить A и нить B ждут, когда замки друг друга заставят бесконечный мертвый цикл для продолжения программы. Конечно, это только ограничено этим. Если вы спросите, как написать программу тупика, вы не узнаете. Говоря, вы не понимаете, что такое тупик. Если вы понимаете теорию, вы будете сделаны. В основном вы не можете увидеть проблему тупика на практике.
Чтобы по -настоящему понять, что такое тупик, этот вопрос не сложно, есть несколько шагов:
(1) Два потока содержат два объекта объекта: Lock1 и Lock2 соответственно. Эти два замка служат блокировками для синхронных кодовых блоков;
(2) В методе run () потока 1 код синхронизации сначала получает блокировку объекта Lock1, Thread.sleep (xxx), время не займет слишком много, 50 миллисекунд почти одинаковы, а затем получает блокировку объекта Lock2. Это в основном сделано, чтобы предотвратить непрерывное получение потока 1 блокировки объектов двух объектов: lock1 и lock2.
(3) Запуск потока 2) (в методе код синхронизации сначала получает блокировку объекта, а затем получает блокировку объекта1.
Таким образом, после потока 1 «Sleeps» и потока 2 приобрели Lock2 объекта. Поток 1 пытается приобрести Lock2 объекта в настоящее время и заблокирована. В настоящее время формируется тупик. Я больше не буду писать код, он занимает много места. Java MultiThreading 7: Законный тупик Эта статья содержит реализацию кода приведенных выше шагов.
24. Как разбудить блокирующую нить
Если потоки блокируются из -за вызова wait (), sleep () или join () методов, он может прервать поток и разбудить его, выбрасывая прерывание; Если поток встречается с блокировкой IO, она бессилена, потому что IO реализуется операционной системой, а код Java не может напрямую связаться с операционной системой.
25. Какая помощь помогает неизменные объекты помогают многопоточному чтению
Проблема, упомянутая выше, заключается в том, что неизменные объекты гарантируют видимость памяти объектов, и нет необходимости в дополнительной синхронизации для чтения неподвижных объектов, что повышает эффективность выполнения кода.
26. Что такое многопоточный переключение контекста
Многопоточное переключение контекста относится к процессу переключения управления процессором из одного запуска потока на другой поток, готовую и ожидание права на выполнение ЦП.
27. Если очередь пула потоков заполнена, когда вы отправляете задачу, что произойдет в настоящее время
Если вы используете LinkedBlockingQueue, то есть без ограниченных очередей, это не имеет значения. Продолжайте добавлять задачи в очередь блокировки и ждать выполнения, потому что LinkedBlockingQueue можно считать бесконечной очередью и может бесконечно хранить задачи; Если вы используете ограниченную очередь, например, ArrayblockingQueue, задача будет добавлена в ArrayBlockingQueue. Если ArrayBlockingQueue заполнена, DecuceedExecutionHandler будет использовать политику отказа для выполнения полных задач, а по умолчанию прерван.
28. Какой алгоритм планирования потоков используется на Java?
Упреждающий стиль. После того, как поток использует процессор, операционная система будет рассчитывать общий приоритет на основе таких данных, как приоритет потока, голод потока и т. Д., И выделять следующий раз, когда срезает поток для выполнения.
29. Какова функция Thread.sleep (0)
Этот вопрос связан с приведенным выше вопросом, и я все вместе. Поскольку Java использует алгоритм расписания с превентивным потоком, может возникнуть, что поток часто получает управление процессором. Чтобы позволить некоторым потокам с относительно низким приоритетом для получения управления процессором, Thread.sleep (0) может использоваться для вручную запустить операционную систему, выделяющую срезы времени, что также является операцией для баланса управления ЦП.
30. Что такое вращение
Многие синхронизированные коды - это просто очень простой код, а время выполнения очень быстрое. Заблокирование потоков, ожидающих в настоящее время, может быть не стоящей работой, потому что блокировка потока включает в себя переключение пользовательского государства и ядра. Поскольку код в синхронизированном виде выполняется очень быстро, вы также можете позволить потоке ожидания блокировки не заблокировать, а вместо этого выполнять занятые петли на границе синхронизации. Это вращение. Если вы сделали несколько занятых петель и обнаружили, что блокировка не была получена, а затем заблокируйте его, это может быть лучшей стратегией.
31. Что такое модель памяти Java
Модель памяти Java определяет спецификацию для многопоточного доступа к памяти Java. Модель памяти Java должна быть полностью объяснена, но я не могу ясно объяснить это в нескольких предложениях здесь. Позвольте мне кратко подвести итоги.
Несколько частей модели памяти Java:
(1) Модель памяти Java делит память на основную память и рабочую память. Состояние класса, то есть переменные, разделенные между классами, хранятся в основной памяти. Каждый раз, когда поток Java использует эти переменные в основной памяти, он будет считывать переменные в основной памяти и позволяет им существовать в своей собственной рабочей памяти. При запуске собственного кода потока он использует эти переменные и управляет тем, что в своей собственной рабочей памяти. После выполнения кода потока последнее значение будет обновлено до основной памяти.
(2) Несколько атомных операций определены для эксплуатации переменных в основной памяти и рабочей памяти
(3) Определите правила использования летучих переменных
(4) случается, прежде чем, то есть принцип первого возникновения, определяет некоторые правила, в которых операция A должна сначала происходить в операции B. Например, код перед потоком управления в том же потоке должен происходить сначала в коде потока управления, что действие освобождения от разблокировки блокировки должно происходить в первую очередь в действии, чтобы заблокировать один и тот же замк и т. Д. До тех пор, пока эти правила не будут выполнены, не требуются дополнительные меры синхронизации. Если определенный фрагмент кода не соответствует всем случаям, потому что это правила, то этот кусок кода должен быть нитью не безопасным.
32. Что такое CAS
CAS, полное имя сравнить и установить, сравнивается. Предположим, есть три операнда: значение памяти V, старое ожидаемое значение A, значение B, которое будет изменено. Если и только если ожидаемое значение A и значение памяти V одинаковы, значение памяти будет изменено на B и возвращено true, в противном случае ничего не будет сделано, и false будет возвращено. Конечно, CAS должен сотрудничать с летучей переменной, чтобы гарантировать, что переменная, полученная каждый раз, является последним значением в основной памяти. В противном случае старое ожидаемое значение A всегда будет значением A, которое не будет изменяться для потока. Пока определенная операция CAS не удается, она никогда не будет успешной.
33. Что такое оптимистичная блокировка и пессимистическая блокировка
(1) Оптимистическая блокировка: точно так же, как его название, он оптимистичен в отношении проблем безопасности потоков, вызванных одновременными операциями. Оптимистичный Lock считает, что конкуренция не всегда происходит, поэтому ей не нужно удерживать блокировку и сравнивать - установить эти два действия в качестве атомной операции, чтобы попытаться изменить переменные в памяти. Если это не удается, это означает, что возникает конфликт, а затем должна быть соответствующая логика повторной попытки.
(2) Пессимистическая блокировка: точно так же, как его название, он пессимистичен в отношении проблем безопасности потоков, вызванных одновременными операциями. Пессимистические замки считают, что конкуренция всегда будет происходить. Следовательно, каждый раз, когда ресурс будет управлять, он будет иметь эксклюзивный замок, как синхронизированный, независимо от того, заблокирован ли он напрямую, и ресурс будет работать.
34. Что такое aqs
Давайте кратко поговорим о AQS. Полное название AQS AbstractQueudsychroNizer. Это должен быть абстрактный синхронизатор очереди при переводе.
Если основой java.util.concurrent является CAS, то AQS является ядром всего пакета параллелизма Java, а также Reentrantlock, CountDownLatch, Semaphore и т. Д. Все используют его. AQ фактически соединяет всю запись в виде двунаправленной очереди. Например, Reentrantlock. Все резьбы ожидания помещаются в запись и соединены в двунаправленную очередь. Если предыдущий поток использует Reentrantlock, то первая запись двунаправленной очереди фактически начинает работать.
AQS определяет все операции на двунаправленных очереди, но открывает только методы Trylock и TryRelease для разработчиков. Разработчики могут переписать методы TryLock и TryRelease в соответствии с их собственной реализацией для реализации своих собственных функций параллелизма.
35. Безопасность нити режима Синглтона
Клише-проблема, первое, что скажет, это то, что безопасность нити синглтонского рисунка означает, что: экземпляры определенного класса будут создаваться только один раз в многопоточной среде. Есть много способов написать односложенный шаблон, позвольте мне суммировать:
(1) Написание синглтонского рисунка голодного человека: безопасность нити
(2) Написание Lazy Singleton Pattern: Nontread-Safe
(3) Напишите режим однолетной блокировки двойной проверки: безопасность потока
36. Какова функция семафора
Semaphore - это семафор, и его функция заключается в ограничении количества параллелизма в определенном кодовом блоке. Semaphore имеет конструктор, который может передавать Int Integer N, указывая, что только n потоки могут получить доступ к определенной части кода. Если n превышается, подождите, пока поток не завершит блок кода, и введите следующий поток. Исходя из этого, мы видим, что если Int Integer n = 1, пройденное в семафорном конструкторе, эквивалентно синхронизированию.
37. Существует только одно утверждение «количество возврата» в методе размера () хэштата, так зачем вам все еще нужно синхронизировать?
Это путаница, которую я имел раньше, и мне интересно, думали ли вы об этом вопросе. Если в методе есть несколько операторов, и все они работают с одной и той же переменной класса, то если вы не добавляете блокировки в многопоточную среду, это неизбежно вызовет проблемы безопасности потоков. Это легко понять, но метод Size () явно имеет только одно утверждение, так зачем вам все еще нужно добавлять замки?
Что касается этой проблемы, я понял это посредством работы и обучения, и есть две основные причины:
(1) Только один поток может одновременно выполнять метод синхронизации фиксированного класса, но для асинхронного метода класса несколько потоков могут получить к нему одновременно. Итак, есть проблема. Возможно, поток A добавляет данные при выполнении метода PUT Hashtable, и поток B может вызывать метод Size () обычно для чтения количества текущих элементов в хэштебе. Чтение значения может быть не последним. Возможно, поток A добавил данные, но без размера ++ поток B уже прочитал размер. Таким образом, для потока B чтение размера должно быть неточным. После добавления синхронизации в метод Size () это означает, что поток B вызывает метод size () только после того, как резьба вызывает метод POT, который обеспечивает безопасность потока
(2) ЦП выполняет код, но это не код Java. Это очень важно, и вы должны это помнить. Код Java в конечном итоге переводится в код сборки для выполнения, а код сборки - это код, который может действительно взаимодействовать с аппаратными целями. Даже если вы видите, что существует только одна строка кода Java, и даже если вы видите, что код Java составлен, сгенерированная только одна строка, это не означает, что для базового уровня есть только одна операция для этого утверждения. Предложение «количество возврата» предполагает, что оно переведено в три оператора сборки для выполнения, и вполне возможно, что поток переключится после выполнения первого предложения.
38. Какой поток является конструктором класса резьбы и статическим блоком, вызванным, по которому поток
Это очень сложный и хитрый вопрос. Пожалуйста, помните: конструктор и статический блок класса потока вызываются потоком, где расположен новый класс потока, а код в методе выполнения называется самим потоком.
Если приведенное выше утверждение смущает вас, тогда позвольте мне привести пример, предположим, что новый Thread1 находится в Thread2, а новый Thread2 находится в основной функции, тогда:
(1) Конструктор Thread2 и статический блок вызываются основным потоком, а метод Thread2 run () вызывается самим потоком2
(2) Конструктор и статический блок Thread1 вызываются Thread2, а метод Thread1 run () вызывается самим потоком1
39. Какой выбор между методом синхронизации и блоком синхронизации является лучшим?
Синхронизировать блоки, что означает, что код вне блока синхронизации выполняется асинхронно, что повышает эффективность кода более эффективной, чем синхронизация всего метода. Пожалуйста, знайте один принцип: меньший диапазон синхронизации
Тем лучше.
В этой статье я хотел бы упомянуть, что, хотя чем меньше диапазон синхронизации, тем лучше, в виртуальных машинах Java все еще существует метод оптимизации, который должен увеличить диапазон синхронизации. Это полезно. Например, StringBuffer-это безопасный класс. Естественно, наиболее часто используемый метод Append () является методом синхронизации. Когда мы пишем код, мы будем неоднократно добавлять строку, что означает многократно блокировка -> разблокировка, что не подходит для производительности, потому что это означает, что виртуальная машина Java должна многократно переключаться между состоянием ядра и состоянием пользователя в этом потоке. Таким образом, виртуальная машина Java выполняет операцию блокировки кода на коде, называемом несколькими методами добавления, расширяя несколько операций приложения на голову и хвост метода добавления, и превращая его в большой блок синхронизации. Это уменьшает количество времени блокировки-> разблокировки, эффективно повышая эффективность выполнения кода.
40. Как использовать пулы потоков для предприятий с высоким параллелизмом и коротким временем выполнения задач? Как использовать пулы потоков для предприятий с низким параллелизмом и длительным временем выполнения задач? Как использовать пулы потоков для предприятий с высоким параллелизмом и длительным временем выполнения услуг?
Это вопрос, который я видел на сайте одновременного программирования. Я поместил этот вопрос и надеюсь, что все могут увидеть и подумать об этом, потому что этот вопрос очень хороший, очень практичный и очень профессиональный. Что касается этой проблемы, мое личное мнение:
(1) Высокая параллелизм и короткое время выполнения задач, количество потоков пула потоков может быть установлено на номер ядра процессора +1, чтобы уменьшить переключение контекста потока.
(2) Предприятия с низким параллелизмом и длительным временем выполнения задач должны рассматриваться отдельно:
a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以加大线程池中的线程数目,让CPU处理更多的业务
b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换
(3)并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦。
Java线程阻塞(Blocked)的类型:
调用sleep函数进入睡眠状态,Thread.sleep(1000)或者TimeUnit.SECONDS.sleep(1),sleep不会释放锁。
等待(wait)某个事件,分为两种,(wait,notify,notifyAll),(await, signal,signalAll) ,后面会详细介绍。wait和await会释放锁,且必须在获取到锁的环境才能调用。
等待锁,synchronized和lock环境中,锁已经被别的线程拿走,等待获取锁。
IO阻塞(Blocked),比如网络等待,文件打开,控制台读取。System.in.read()。