Четыре использования и сценарии использования пула потоков Java

Java

1. Существуют следующие проблемы

new Thread() {
    @Override
    public void run() {
        // 业务逻辑
    }
}.start();
  • Во-первых, частое создание и уничтожение объектов — очень требовательная к производительности вещь;
  • Если количество пользователей относительно велико, что приводит к занятию слишком большого количества ресурсов, наша служба может быть недоступна из-за нехватки ресурсов;
  • Подводя итог, в реальной разработке, этот вид операции на самом деле не рекомендуется.

2. Каковы преимущества использования пулов потоков?

  • Увеличена скорость использования потоков в пуле потоков, а также уменьшено создание и уничтожение объектов;
  • Пул потоков может контролировать количество потоков, эффективно улучшать ресурсы, используемые сервером, и избегать таких проблем, как простои из-за нехватки ресурсов;

Три, четыре способа использования пула потоков

1. новый кэшированный пул потоков

  • Создайте пул потоков. Если количество потоков в пуле потоков слишком велико, он может эффективно перерабатывать лишние потоки. Если количество потоков недостаточно, он может создавать новые потоки.
public static void method() throws Exception {

    ExecutorService executor = Executors.newCachedThreadPool();

    for (int i = 0; i < 5; i++) {

        final int index = i;

        Thread.sleep(1000);

        executor.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "  " + index);
            }
        });
    }
}

Результаты

image

Анализируя, я вижу, что он выполняется одним потоком от начала до конца, что реализует повторное использование потоков и не создает избыточных потоков.

Если и когда нашему бизнесу потребуется определенное время для обработки, что произойдет. Давайте смоделируем это.

image

Хорошо видно, что теперь требуется поочередное выполнение нескольких потоков.

  • недостаточный: хотя этот метод может автоматически увеличивать количество потоков для обработки нашего бизнеса в соответствии с бизнес-сценарием, мы не можем контролировать максимальное количество потоков, необходимых для обработки дефицита одновременно;
  • преимущество: если первая задача была выполнена при запуске второй задачи, вторая задача будет повторно использовать поток, созданный первой задачей, и не будет повторно создавать новый поток, что повышает скорость повторного использования потока;

2. новый фиксированный пул потоков

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

Сначала проверьте максимальную мощность одного потока, тогда это будет результат нашего прогноза.

public static void method_01() throws InterruptedException {

    ExecutorService executor = Executors.newFixedThreadPool(1);

    for (int i = 0; i < 10; i++) {

        Thread.sleep(1000);
        final int index = i;

        executor.execute(() -> {
            try {
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "  " + index);
        });
    }
    executor.shutdown();
}

Результаты

image

Давайте перейдем на 3 потока и посмотрим на результаты

image

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

3. новый запланированный пул потоков

Пул потоков поддерживает синхронизацию и периодическое выполнение задачи.Мы можем отложить время выполнения задачи или установить периодическое время для повторения задачи. В этом пуле потоков есть два следующих метода задержки.

  • scheduleAtFixedRate

тест один

public static void method_02() {
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

    executor.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            long start = new Date().getTime();
            System.out.println("scheduleAtFixedRate 开始执行时间:" +
                    DateFormat.getTimeInstance().format(new Date()));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long end = new Date().getTime();
            System.out.println("scheduleAtFixedRate 执行花费时间=" + (end - start) / 1000 + "m");
            System.out.println("scheduleAtFixedRate 执行完成时间:" + DateFormat.getTimeInstance().format(new Date()));
            System.out.println("======================================");
        }
    }, 1, 5, TimeUnit.SECONDS);
}

Результаты

image

Тест два

image

Суммировать: разница между двумя вышеуказанными методами заключается во времени выполнения задачи.Если время интервала больше, чем время выполнения задачи, время выполнения не влияет на задачу. Если время интервала меньше времени выполнения задачи, задача будет выполнена сразу после выполнения задачи, и время интервала будет сорвано.

  • scheduleWithFixedDelay

тест один

public static void method_03() {
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

    executor.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            long start = new Date().getTime();
            System.out.println("scheduleWithFixedDelay 开始执行时间:" +
                    DateFormat.getTimeInstance().format(new Date()));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long end = new Date().getTime();
            System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");
            System.out.println("scheduleWithFixedDelay执行完成时间:"
                    + DateFormat.getTimeInstance().format(new Date()));
            System.out.println("======================================");
        }
    }, 1, 2, TimeUnit.SECONDS);
}

Результаты

image

Тест два

public static void method_03() {
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

    executor.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            long start = new Date().getTime();
            System.out.println("scheduleWithFixedDelay 开始执行时间:" +
                    DateFormat.getTimeInstance().format(new Date()));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long end = new Date().getTime();
            System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 + "m");
            System.out.println("scheduleWithFixedDelay执行完成时间:"
                    + DateFormat.getTimeInstance().format(new Date()));
            System.out.println("======================================");
        }
    }, 1, 2, TimeUnit.SECONDS);
}

Результаты

image

Суммировать: Аналогично методу проверки scheduleWithFixedDelay можно определить, что на интервал времени scheduleWithFixedDelay время выполнения задачи не повлияет.

4. новый однопоточный исполнитель

Это однопоточный пул, исполняемый одним потоком от начала до конца.

public static void method_04() {

    ExecutorService executor = Executors.newSingleThreadExecutor();

    for (int i = 0; i < 5; i++) {
        final int index = i;
        executor.execute(() -> {
            try {
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "   " + index);
        });
    }
    executor.shutdown();
}

Результаты

image

В-четвертых, роль пула потоков

Роль пула потоков в основном заключается в повышении производительности и использовании системы.. Как упоминалось в начале статьи, если использовать простейший способ создания потоков, если число пользователей относительно велико, то действий по созданию и уничтожению потоков будет много, что приведет к потребляемой производительности сервер в создании и уничтожении потоков.Это требует больше времени и производительности, чем обработка фактического бизнеса. Пул потоков был создан для решения такого рода проблем.

Есть много дизайнов с той же идеей, например,пул соединений с базой данных, Однако из-за частого подключения к базе данных создание подключения является очень ресурсоемкой задачей, и появляются все пулы подключений к базе данных.