Во время работы и собеседования я столкнулся с множеством проблем с многопоточностью. Здесь я резюмирую это, я надеюсь, что это поможет вам. Содержание этой статьи в основном представляет собой несколько контрпримеров, некоторые из которых очень низкоуровневые, но распространенные.
Конечно, также отлично использовать его в качестве принуждения во время интервью.
10 первый.
я оценю
1. Желание создать пул потоков
Феномен:Системные ресурсы исчерпаны, а процессы мертвы.
причина:При каждом выполнении метода создается новый пул потоков.
Решение по вкусу мисс сестра: поделитесь пулом потоков.
Класс смерти:пять звезд
Уровень безумия:пять звезд
void doJob(){
ThreadPoolExecutor exe = new ThreadPoolExecutor(...);
exe.submit(new Runnable(){...})
}
2. Блокировка утечки
Феномен:Поток удерживает блокировку и не освобождает ее, вызывая утечку блокировки.
причина:Неизвестное исключение или логика заставили функцию разблокировки не выполняться.
Решение по вкусу мисс сестра: всегда устанавливайте функцию разблокировки, наконец.
Класс смерти:три звезды
Уровень безумия:четыре звезды
private final Lock lock = new ReentrantLock();
void doJob(){
try{
lock.lock();
//do. sth
lock.unlock();
}catch(Exception e){
}
}
3. Забыть синхронизировать переменные
Феномен:При определенных условиях выбрасывается исключение IllegalMonitorStateException.
причина:Вызовите ожидание, уведомите и т. д., забудьте о синхронизации или синхронизируйте неправильную переменную.
Решение мисс сестра вкус: перед вызовом этих функций, используйте ключевое слово синхронизации для синхронизации.
Класс смерти:две звезды
Уровень безумия:четыре звезды
Object condition = new Object();
condition.wait();
4. Бесконечный цикл HashMap
Феномен:Загрузка ЦП высокая, возникает бесконечный цикл, использование jstack для его просмотра заблокировано в методе get.
причина:При определенных условиях при выполнении перефразирования будет образовываться циклическая цепочка. Определенные запросы на получение будут ходить по этому кольцу.
Вкусовое решение от Miss Sister: в многопоточной среде используйте ConcurrentHashMap, не раздумывая.
Класс смерти:четыре звезды
Уровень безумия:четыре звезды
5. Переназначить синхронизированные переменные
Феномен:Эффект синхронизации не может быть достигнут, и результат неправильный.
причина:Небазовый тип переназначается, что изменит направление блокировки, а блокировки, удерживаемые разными потоками, могут быть разными.
Решение по вкусу мисс сестра: объявите объект блокировки окончательным типом.
Класс смерти:четыре звезды
Уровень безумия:три звезды
List listeners = new ArrayList();
void add(Listener listener, boolean upsert){
synchronized(listeners){
List results = new ArrayList();
for(Listener ler:listeners){
...
}
listeners = results;
}
}
Шесть, неперехваченное исключение петли потока
Феномен:Задание потока не может продолжать выполняться и прервано по необъяснимым причинам.
причина:Исключение в необработанном цикле привело к завершению потока.
Решение вкуса мисс сестра: привычно ловить все исключения.
Класс смерти:три звезды
Уровень безумия:три звезды
volatile boolean run = true;
void loop(){
while(run){
//do . sth
int a = 1/0;
}
}
Семь, летучие ошибочно приняты за счетчик
Феномен:Неверный результат подсчета многопоточности.
причина:Volatile гарантирует видимость, но не гарантирует атомарность, а многопоточные операции не гарантируют корректность.
Решение по вкусу мисс сестра: используйте класс Atomic напрямую.
Класс смерти:три звезды
Уровень безумия:две звезды
volatile count = 0;
void add(){
++count;
}
8. Объем защиты от ошибок
Феномен:Несмотря на то, что используются потокобезопасные коллекции, синхронизация не достигается.
причина:Операция изменяет несколько потокобезопасных коллекций, но сама операция не является атомарной.
Решение по вкусу мисс сестра: выясните область логики кода, которую необходимо защитить.
Класс смерти:три звезды
Уровень безумия:четыре звезды
private final ConcurrentHashMap<String,Integer> nameToNumber;
private final ConcurrentHashMap<Integer,Salary> numberToSalary;
public int geBonusFor(String name) {
Integer serialNum = nameToNumber.get(name);
Salary salary = numberToSalary.get(serialNum);
return salary.getBonus();
}
Другим примером является приведенный ниже код ошибки.
Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
if(!map.containsKey("foo"))
map.put("foo", "bar");
9. Некоторые старые классы обработки данных
Феномен:Используйте глобальный Calendar, SimpleDateFormat и т. д. для обработки даты, возникновения исключения или данных неточны.
причина:Эти две вещи не являются потокобезопасными, и будут проблемы с одновременными вызовами.
Мисс сестра по вкусу: поместите его в ThreadLocal, рекомендуется использовать потокобезопасный DateTimeFormatter.
Класс смерти:три звезды
Уровень безумия:три звезды
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date dododo(String str){
return format(str);
}
10. Кодовый тупик
Феномен:Код взаимоблокируется и ждет друг друга.
причина:Код удовлетворяет следующим четырем условиям: взаимное исключение, неотчуждаемость, запрос и удержание, циклическое ожидание.
Решение вкуса мисс сестра: разрушьте эти четыре условия. Или используйте меньше синхронизации.
Класс смерти:две звезды
Уровень безумия:звезда
Ниже приведен простой код взаимоблокировки.
final Object lock1 = new Object();
final Object lock2 = new Object();
new Thread(new Runnable() {
@Override
public void run() {
sleep(1000);
synchronized (lock1) {
synchronized (lock2) {
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock2) {
sleep(1000);
synchronized (lock1) {
}
}
}
}).start();
Одиннадцать, длинная переменная считывает недопустимое значение
Феномен:Неустановленное значение будет прочитано.
причина:Чтение и запись длинных переменных не являются атомарными и могут считывать старшие 32 бита одной переменной и младшие 32 бита другой переменной.
Решение Miss Sister: убедитесь, что данные длинных и двойных переменных верны, вы можете добавить ключевое слово volatile.
Класс смерти:звезда
Уровень безумия:нет звезды
Расширенное чтение (jdk10):docs.Oracle.com/JavaColor/spec…
Хм? Откуда 11? Это должно быть многопоточной ошибкой расчета.
End
Многие Java-разработчики плохо знакомы с многопоточной разработкой. Но даже опытные разработчики могут попасть во множество多线程
ловушка. Когда ваша программа не имеет соответствующих ожиданий, надеюсь, эта статья поможет вам разобраться в тонкостях.
Использование многопоточности чрезвычайно сложно, вероятность ошибок при использовании низкоуровневых API будет увеличиваться в геометрической прогрессии, а требования к навыкам также высоки. К счастью, пакет concurrent значительно упрощает этот процесс, но проблемы с планированием ресурсов и сбоями синхронизации все еще остаются. Вот относительно простое, но исчерпывающее описание вкуса Miss Sister:Многопоточные сценарии использования JAVA и меры предосторожности, но надежный код зависит от вас, чтобы попрактиковаться.
Больше отличных статей.
«Микросервисы — это не все, а лишь подмножество определенного домена».
С таким количеством компонентов мониторинга всегда найдется подходящий для вас
«Наиболее часто используемый набор навыков «vim» в производственной среде Linux.
«С Нетти, что мы разрабатываем? 》
Линукс из пяти частей и тому подобное.
«Остальная часть необитаемого острова» Linux (1) Подготовка»
«Linux« Остальная часть необитаемого острова »(2) Глава CPU»
«Linux« Остальная часть необитаемого острова »(3) глава памяти»
«Linux« Остальная часть необитаемого острова »(4) глава ввода-вывода»
«Сетевая глава Linux« Оставшаяся жизнь на необитаемом острове »(5)»
Больше, пожалуйста, следуйте. Конечно, вы также можете подписаться на публичный аккаунт.