Вообще говоря, отлаживать многопоточный параллелизм и условные точки останова сложно, возможно, эта статья предоставит вам удобный метод отладки. Сделайте отладку в многопоточном процессе разработки более целенаправленной.
Мы будем учиться на примере. Здесь я написал многопоточную программу для расчета этой математической задачи:100! + 100000!
. То есть: факториал 100 + факториал 100000.
Для студентов, которые плохо разбираются в математике, смотрите здесь Факториал 100: 1 * 2 * 3 * ...... * 100 = ? , сокращенно 100!
import java.math.BigInteger;
public class MathProblemSolver {
//开启两个线程
public static void main(String arg[]){
//第一个线程计算 100!
FactorialCalculatingThread thread1 = new FactorialCalculatingThread(100);
//第二个线程计算 100000!
FactorialCalculatingThread thread2 = new FactorialCalculatingThread(100000);
thread1.setName("Thread 1");
thread2.setName("Thread 2");
thread1.start();
thread2.start();
try {
thread1.join(); //线程Jion,以使主线程在“线程1”和“线程2”都返回结果之前不会进一步执行
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
BigInteger result = thread1.getResult().add(thread2.getResult());
System.out.println("将两个线程的计算结果相加等于:" + result);
}
//用于阶乘计算的线程类
private static class FactorialCalculatingThread extends Thread {
private BigInteger result = BigInteger.ONE;
private long num;
public FactorialCalculatingThread(long num) {
this.num = num;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 开始阶乘的计算:" + num);
factorialCalc(num);
System.out.println(Thread.currentThread().getName() + "执行完成");
}
//数的阶乘计算方法
public void factorialCalc(long num) {
BigInteger f = new BigInteger("1");
for (int i = 2; i <= num; i++)
f = f.multiply(BigInteger.valueOf(i));
result = f;
}
public BigInteger getResult() { return result; }
}
}
Приведенный выше код объяснил
- Запустите два потока, расчет «Поток 1» (100!) и расчет «Поток 2» (100000!)
- Запустите два потока в методе main(), затем вызовите
thread1.join()
иthread2.join()
, так что основной поток не будет выполняться дальше, пока оба "потока 1" и "потока 2" не вернут результаты. - Наконец, результаты расчета двух потоков добавляются для получения
100! + 100000!
Давайте воспользуемся инструментом IntelliJ IDEA для отладки этого многопоточного кода.
Панель «Рамки и нити»
"Окно средства отладки"Панель «Рамки»Содержит раскрывающееся меню. Он фокусируется на потоках, приостановленных из-за точек останова, и отображает информацию о стеке вызовов для этих потоков. На изображении ниже точка останова находится в позиции, показанной в методе main(), а Frame показывает нам стек вызовов основного потока.
Если вы хотите проверить стеки вызовов других потоков, вы можете выбрать из раскрывающегося списка.
Панель с резьбойПоказывает все потоки, которые в данный момент активны. Ссылаясь на приведенный выше код, я нахожусь вthread1.join()
Добавлена точка останова. Когда приложение приостановлено в этой точке останова, мы должны увидеть как минимум три потока на этой панели — «основной», «Поток 1» и «Поток 2» (см. снимок экрана ниже). Вы можете дважды щелкнуть по каждому потоку, чтобы просмотреть его стек вызовов.
Условные точки останова — приостановить только подходящие потоки
Допустим, я работаю над ошибкой в этой программе, и мне нужно только приостановить выполнение, когда запустится «Поток 2». Это говорит о том, что мне нужно добавить точку останова в первую строку метода run() класса FactorialCalculatoringThread. Поскольку два запущенных нами потока используют один и тот же фрагмент кода, у нас есть проблема: все потоки, использующие этот фрагмент кода, будут приостановлены при достижении точки останова, включая "Поток 1" и "Поток 1" 2 приложения. Я не хочу, чтобы оба потока были приостановлены. Как сделать?
Мы можем использовать функцию условной точки останова. После добавления точки останова щелкните ее правой кнопкой мыши, установите флажок «Приостановить» и выберите «Поток». Затем добавляем условиеcurrentThread().getName().equals("Thread 2")
, как показано на скриншоте ниже. Это условие гарантирует, что отладчик приостановит текущий поток только в том случае, если его имя "Thread 2":
Теперь при выполнении отладчика, когда приложение приостанавливается, приостанавливается только «Поток 2». Вы можете убедиться, что «Поток 1» выполнен и не приостановлен, выполнив следующие действия:
1. В консоли по логам можно убедиться, что "Thread 1" запустился и завершился.
2. В панели «Поток» видно, что в данный момент «Потока 1» нет, а операция завершена!
Условные точки останова могут быть настроены по-разному в разных версиях IDE. Но ключевая идея заключается в том, чтобы знать об этих функциях и использовать их.
Добро пожаловать, чтобы обратить внимание на мой блог, в нем много прекрасных коллекций
- Эта статья воспроизводится с указанием источника (должна быть ссылка, а не только текст):Блог Адетокунбо.
Если вы считаете это полезным, пожалуйста, лайкните и поделитесь! Ваша поддержка - моя неиссякаемая творческая мотивация!. Кроме того, автор недавно выпустил следующий прекрасный контент, с нетерпением жду вашего внимания.