[Комикс] Инструмент моделирования параллелизма для параллельного программирования JAVA

Java

Оригинал заявления: Эта статья взята из публичного аккаунта [Fat Pig Learning Programming], пожалуйста, укажите источник для перепечатки.

предыдущий раздел[Комикс] Три основных источника ошибок в параллельном программировании на JAVA (видимость, атомарность, упорядоченность)Мы говорили о трех источниках ошибок в параллельном программировании. Прежде чем это начало проникать в параллельный мир, жирная свинья столкнулась с проблемой. .

Эта головоломка — загадка, которая есть у всех новичков: нет никакого способа воспроизвести ошибки, о которых говорит нам теоретическое знание. Но реальная практика очень важна, так как же смоделировать параллелизм в локальной среде разработки?

_1

Полный набор инструментов параллельного моделирования

Существует множество способов локального моделирования параллельной среды, наиболее популярными из которых являются следующие, включая инструменты и коды:

1. Почтальон: инструмент моделирования HTTP-запросов, который можно настроить для инициирования N запросов (но не рекомендуется, не профессионально).

2. Apache Bench (AB): инструмент веб-нагрузочного тестирования для сервера Apache.Это инструмент командной строки, который может создавать множество потоков параллельного доступа в соответствии с командами, имитируя одновременный доступ нескольких посетителей к URL-адресу. В целом, инструмент ab небольшой и простой, быстрый в освоении и может обеспечить необходимые базовые показатели производительности, но недостатком является отсутствие графического результата и невозможность его мониторинга.

3. Apache JMeter: инструмент стресс-тестирования на основе Java, разработанный организацией Apache. По сравнению с AB функция будет более мощной, особенно графический интерфейс GUI, что очень круто. Кроме того, jmeter — это полный запрос и возврат, АБ просто отправляет запрос и не обрабатывает возврат. Если вы хотите увидеть возвращаемые результаты, вам также следует выбрать JMeter.

4. Код JAVA: включая CountDownLatch, CyclicBarrier и т. д.

В основном мы говорим о том, как смоделировать параллельную среду с помощью jmeter и кода, и эти два метода также рекомендуются.

CountDownLatch (ожидание завершения многопоточности)

Оригинал заявления: Эта статья взята из публичного аккаунта [Fat Pig Learning Programming], пожалуйста, укажите источник для перепечатки.

countDownLatch появился в java1.5 и существует в составе пакета java.util.cucurrent.

Этот класс позволяетПоток ожидает, пока другие потоки завершат свое выполнение перед выполнением.

Он реализуется счетчиком, начальным значением которого является количество потоков. Всякий раз, когда поток завершает выполнение, значение счетчика равно -1.Когда значение счетчика равно 0, это означает, что все потоки завершили выполнение, и тогда поток, ожидающий блокировки, может возобновить работу.

Как показано на рисунке, при начальном значении cnt=3 поток A выполняет метод await, поэтому он блокируется и ожидает, поток T1\T2\T3 вызывает countDown для уменьшения счетчика на единицу, а поток A не возобновляет работу. работает до тех пор, пока cnt=0. Другими словами, поток A должен дождаться завершения выполнения трех других потоков:image

В классе countDownLatch предоставляется только один конструктор:

//参数count为计数值
public CountDownLatch(int count) {  };
countDownLatch类中有三个方法是最重要的:

//Поток, вызывающий метод await(), будет приостановлен, он будет ждать, пока значение счетчика не станет равным 0, прежде чем продолжить выполнение

public void await() throws InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
//将count值减1
public void countDown() { };

Пример: требуется обработать Excel, а в Excel много строк данных.Для эффективности мы можем использовать многопоточную обработку, но после обработки всех строк данных нам нужно уведомить основной поток. Если нет countDownLatch, то эффект такой, можно сказать, что я кончил еще до его завершения:

image

Если countDownLatch добавляется к основному потоку и вызывается метод await(), основной поток будет приостановлен и будет ждать, пока значение счетчика не станет равным 0, прежде чем продолжить:

    static CountDownLatch countDownLatch = new CountDownLatch(100);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(() -> {
                doWork();
                countDownLatch.countDown();
            });
            thread.start();

        }
        countDownLatch.await();
        System.out.println("处理完整个excel的结束时间"+System.currentTimeMillis());
    }

    public static void doWork(){
        System.out.println("处理行数据,时间"+System.currentTimeMillis());
    }

_2

Thread thread = new Thread(() -> {
    try {
        countDownLatch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    doWork();
});
thread.start();
countDownLatch.countDown();

_3

Пул потоков

 ExecutorService executorService = new ThreadPoolExecutor(100,
         200, 60, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(20000), new ThreadFactory() {
     @Override
     public Thread newThread(Runnable r) {
         return new Thread(r);
     }
 });

CyclicBarrier (барьер синхронизации)

Оригинал заявления: Эта статья взята из публичного аккаунта [Fat Pig Learning Programming], пожалуйста, укажите источник для перепечатки.

CyclicBarrier буквально означает перерабатываемый (циклический) барьер (барьер).. Что он делает, так это блокирует группу потоков, когда они достигают барьера (также называемого точкой синхронизации), до тех пор, пока последний поток не достигнет барьера, барьер откроет дверь, и все потоки, заблокированные барьером, продолжат работу.

Как показано на рисунке ниже, всего имеется 4 потока A, B, C, D, и порядок, в котором они достигают барьера, может быть другим. Когда A, B и C придут к забору, так как они не удовлетворяют требованиям общего числа [4], они будут все время ждать, а когда придет поток D, забор будет освобожден.

image

Циклический способ построения барьера

//其参数表示屏障拦截的线程数量
public CyclicBarrier(int parties)
//多了回调函数
public CyclicBarrier(int parties, Runnable barrierAction)

Основной метод заключается в следующем

//调用await方法的线程告诉CyclicBarrier自己已经到达同步点,然后当前线程被阻塞。直到parties个参与线程调用了await方法,阻塞线程才会执行。
public int await()
//带超时时间参数
public int await(long timeout, TimeUnit unit)
//重置
public void reset()

В соответствии с этой функцией мы также можем использовать его для параллельной симуляции.Следующий код имитирует параллельное выполнение 5 потоков:

  private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

  public static void main(String[] args) throws InterruptedException {
      ExecutorService executorService = ExecutorServiceUtils.getExecutor();
      for (int i = 0; i < 20; i++) {
          int finalI = i;
          Thread.sleep(1000);
          executorService.submit(() -> {
              try {
                  doWork(finalI);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          });
          //通过打印日志 得出它具有自动重置功能
          log.info("Parties={} 等待中{}",cyclicBarrier.getParties(),cyclicBarrier.getNumberWaiting());
      }
      executorService.shutdown();
  }

  public static void doWork(Integer threadNum) throws Exception {
      Thread.sleep(1000);
      log.info("{} is ready", threadNum);
      cyclicBarrier.await();
      log.info("{} continue", threadNum);
  }

Основное различие между CountDownLatch и CyclicBarrier:

1. CountDownLatch в основном используется для решения сценария, когда один поток ожидает несколько потоков, Его можно сравнить с лидером туристической группы, который должен дождаться прибытия всех туристов, прежде чем отправиться в следующее живописное место;

CyclicBarrier — это группа потоков, ждущих друг друга, больше похожих на несколько друзей-осликов.

2. CountDownLatch — это метод обратного счета, а CyclicBarrier — прямой.

3. Счетчик CountDownLatch не может быть перезапущен, то есть, как только счетчик уменьшится до 0 и другой поток вызовет await(), поток пройдет напрямую.

Однако счетчик CyclicBarrier может быть перезапущен и имеет функцию автоматического сброса.Как только счетчик уменьшится до 0, он автоматически сбрасывается до исходного значения, которое вы установили.

4. Кроме того, CyclicBarrier также может устанавливать функции обратного вызова, о которых можно сказать, что они богаты функциями. И CountDownLatch не поддерживает функции обратного вызова.

Что ж, теперь вернемся к невоспроизводимому коду в начале, давайте перепишем его с помощью CyclicBarrier, и вы увидите вхождение 0.

image

Еще хочу сказать: даже если это реальное параллельное выполнение, проблема все же маловероятностное событие.Я лично тестировал 15 раз, прежде чем появился результат 0. Если повезет, вы можете запустить его 100 раз и все равно не увидеть. Не слишком зацикливайтесь на этом!

JMeterTools

1. После загрузки разархивируйте каталог, настройте переменные среды и запустите jmeter.bat.

2. Добавьте группу потоков:

image

3. Настройте связанные свойства группы потоков, в основном количество потоков и необходимость зацикливания.Здесь мы устанавливаем количество одновременных потоков равным 50, и после выполнения каждого потока цикл не требуется:

image

4. Добавьте http-запрос, например запрос, который мы хотим протестировать для интерфейса /test:

image

Настройте формат http ip\port\encoding и т.д.:

image

5. Добавьте два слушателя для просмотра графических результатов и количества результатов после выполнения:

image

6. Запускаем группу потоков для вывода наших результатов

image

Ну вот и все на сегодня, пора со всеми попрощаться~

Оригинал заявления: Эта статья взята из публичного аккаунта [Fat Pig Learning Programming], пожалуйста, укажите источник для перепечатки.

Эта статья воспроизведена с официального аккаунта [Fat Pig Learning Programming] С помощью комиксов программирование становится таким простым и интересным! Добро пожаловать, чтобы обратить внимание!