@Async异步线程池以及线程的命名方式

本文记录@Async的基本使用以及通过实现ThreadFactory来实现对线程的命名。

@Async的基本使用

近日有一个道友提出到一个问题,大意如下:

业务场景需要进行批量更新,已有数据id主键、更新的状态。单条更新性能太慢,所以使用in进行批量更新。但是会导致锁表使得其他业务无法访问该表,in的量级太低又导致性能太慢。

龙道友提出了一个解决方案,把要处理的数据分成几个list之后使用多线程进行数据更新。提到多线程可直接使用@Async注解来进行异步操作。

好的,接下来上面的问题我们不予解答,来说下@Async的简单使用

@Async在SpringBoot中的使用较为简单,所在位置如下:

一.启动类加入注解@EnableAsync

第一步就是在启动类中加入@EnableAsync注解 启动类代码如下:

@SpringBootApplication
@EnableAsync
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

二.编写MyAsyncConfigurer类

MyAsyncConfigurer类实现了AsyncConfigurer接口,重写AsyncConfigurer接口的两个重要方法:

1.getAsyncExecutor:自定义线程池,若不重写会使用默认的线程池。

2.getAsyncUncaughtExceptionHandler:捕捉IllegalArgumentException异常.

一方法很好理解。二方法中提到的IllegalArgumentException异常在之后会说明。代码如下:

/**
 * @author hsw
 * @Date 20:12 2018/8/23
 */
@Slf4j
@Component
public class MyAsyncConfigurer implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        //定义一个最大为10个线程数量的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        return service;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new MyAsyncExceptionHandler();
    }

    class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
            log.info("Exception message - " + throwable.getMessage());
            log.info("Method name - " + method.getName());
            for (Object param : objects) {
                log.info("Parameter value - " + param);
            }
        }
    }
}</code>

三.三种测试方法

1.无参无返回值方法

2.有参无返回值方法

3.有参有返回值方法

具体代码如下:

/**
 * @author hsw
 * @Date 20:07 2018/8/23
 */
@Slf4j
@Component
public class AsyncExceptionDemo {

    @Async
    public void simple() {
        log.info("this is a void method");
    }

    @Async
    public void inputDemo (String s) {
        log.info("this is a input method,{}",s);
        throw new IllegalArgumentException("inputError");
    }

    @Async
    public Future hardDemo (String s) {
        log.info("this is a hard method,{}",s);
        Future future;
        try {
            Thread.sleep(3000);
            throw new IllegalArgumentException();
        }catch (InterruptedException e){
            future = new AsyncResult("InterruptedException error");
        }catch (IllegalArgumentException e){
            future = new AsyncResult("i am throw IllegalArgumentException error");
        }
        return future;
    }
}

在第二种方法中,抛出了一种名为IllegalArgumentException的异常,在上述第二步中,我们已经通过重写getAsyncUncaughtExceptionHandler方法,完成了对产生该异常时的处理。

在处理方法中我们简单列出了异常的各个信息。

ok,现在该做的准备工作都已完成,加个测试方法看看结果如何

/**
 * @author hsw
 * @Date 20:16 2018/8/23
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class AsyncExceptionDemoTest {

    @Autowired
    private AsyncExceptionDemo asyncExceptionDemo;

    @Test
    public void simple() {
        for (int i=0;i<3;i++){
            try {
                asyncExceptionDemo.simple();
                asyncExceptionDemo.inputDemo("input");
                Future future = asyncExceptionDemo.hardDemo("hard");
                log.info(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
}

测试结果如下:

2018-08-25 16:25:03.856 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : Started AsyncExceptionDemoTest in 3.315 seconds (JVM running for 4.184)
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-1] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-3] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:03.947 INFO 4396 --- [pool-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:06.947 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-4] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-6] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:06.948 INFO 4396 --- [pool-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:09.949 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-7] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-9] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:25:09.950 INFO 4396 --- [pool-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:25:12.950 INFO 4396 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:25:12.953 INFO 4396 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@71075444: startup date [Sat Aug 25 16:25:01 CST 2018]; root of context hierarchy

测试成功。

到此为止,关于@Async注解的基本使用内容结束。但是在测试过程中,我注意到线程名的命名为默认的pool-1-thread-X,虽然可以分辨出不同的线程在进行作业,但依然很不方便,为什么默认会以这个命名方式进行命名呢?

线程池的命名

点进Executors.newFixedThreadPool,发现在初始化线程池的时候有另一种方法

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

那么这个ThreadFactory为何方神圣?继续ctrl往里点,在类中发现这么一个实现类。

破案了破案了。原来是在这里对线程池进行了命名。那我们只需自己实现ThreadFactory接口,对命名方法进行重写即可,完成代码如下:

static class MyNamedThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;
    MyNamedThreadFactory(String name) {

        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        if (null == name || name.isEmpty()) {
            name = "pool";
        }

        namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

然后在创建线程池的时候加上新写的类即可对线程名进行自定义。

@Override
public Executor getAsyncExecutor() {
    ExecutorService service = Executors.newFixedThreadPool(10,new MyNamedThreadFactory("HSW"));
    return service;
}

看看重命名后的执行结果。

2018-08-25 16:42:44.068 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : Started AsyncExceptionDemoTest in 3.038 seconds (JVM running for 3.83)
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-3] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-1] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:44.155 INFO 46028 --- [ HSW-1-thread-2] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:47.155 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-4] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-6] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:47.156 INFO 46028 --- [ HSW-1-thread-5] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:50.156 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-7] com.hsw.test.async.AsyncExceptionDemo : this is a void method
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.AsyncExceptionDemo : this is a input method,input
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-9] com.hsw.test.async.AsyncExceptionDemo : this is a hard method,hard
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Exception message - inputError
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Method name - inputDemo
2018-08-25 16:42:50.157 INFO 46028 --- [ HSW-1-thread-8] com.hsw.test.async.MyAsyncConfigurer : Parameter value - input
2018-08-25 16:42:53.157 INFO 46028 --- [ main] c.hsw.test.async.AsyncExceptionDemoTest : i am throw IllegalArgumentException error
2018-08-25 16:42:53.161 INFO 46028 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@71075444: startup date [Sat Aug 25 16:42:41 CST 2018]; root of context hierarchy

Spring Boot使用@Async实现异步调用:自定义线程池

定义线程池

第一步,先在Spring Boot主类中定义一个线程池,比如:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @EnableAsync
    @Configuration
    class TaskPoolConfig {
        @Bean("taskExecutor")
        public Executor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(10);
            executor.setMaxPoolSize(20);
            executor.setQueueCapacity(200);
            executor.setKeepAliveSeconds(60);
            executor.setThreadNamePrefix("taskExecutor-");
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }
    }
}

上面我们通过使用ThreadPoolTaskExecutor创建了一个线程池,同时设置了以下这些参数:

  • 核心线程数10:线程池创建时候初始化的线程数
  • 最大线程数20:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
  • 缓冲队列200:用来缓冲执行任务的队列
  • 允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
  • 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
  • 线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务

使用线程池

在定义了线程池之后,我们如何让异步调用的执行任务使用这个线程池中的资源来运行呢?方法非常简单,我们只需要在@Async注解中指定线程池名即可,比如:

@Slf4j
@Component
public class Task {
    public static Random random = new Random();
    @Async("taskExecutor")
    public void doTaskOne() throws Exception {
        log.info("开始做任务一");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务一,耗时:" + (end - start) + "毫秒");
    }
    @Async("taskExecutor")
    public void doTaskTwo() throws Exception {
        log.info("开始做任务二");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务二,耗时:" + (end - start) + "毫秒");
    }
    @Async("taskExecutor")
    public void doTaskThree() throws Exception {
        log.info("开始做任务三");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("完成任务三,耗时:" + (end - start) + "毫秒");
    }
}

单元测试

最后,我们来写个单元测试来验证一下

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ApplicationTests {
    @Autowired
    private Task task;
    @Test
    public void test() throws Exception {
        task.doTaskOne();
        task.doTaskTwo();
        task.doTaskThree();
        Thread.currentThread().join();
    }
}

执行上面的单元测试,我们可以在控制台中看到所有输出的线程名前都是之前我们定义的线程池前缀名开始的,说明我们使用线程池来执行异步任务的试验成功了!

2018-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task : 开始做任务一
2018-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task : 开始做任务二
2018-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task : 开始做任务三
2018-03-27 22:01:18.165 INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task : 完成任务二,耗时:2545毫秒
2018-03-27 22:01:22.149 INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task : 完成任务三,耗时:6529毫秒
2018-03-27 22:01:23.912 INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task : 完成任务一,耗时:8292毫秒

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈Spring @Async异步线程池用法总结

    本文介绍了Spring @Async异步线程池用法总结,分享给大家,希望对大家有帮助 1. TaskExecutor spring异步线程池的接口类,其实质是Java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程. 2. SyncTaskExecutor:这个类没有实现异步调用,只是一个同步操作.只适用于不需要多线程的地方 3. Conc

  • spring boot使用自定义配置的线程池执行Async异步任务

    在前面的博客中,http://www.jb51.net/article/106718.htm 我们使用了spring boot的异步操作,当时,我们使用的是默认的线程池,但是,如果我们想根据项目来定制自己的线程池了,下面就来说说,如何定制线程池! 一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context.properties.ConfigurationP

  • Spring Boot利用@Async如何实现异步调用:自定义线程池

    前言 在之前的Spring Boot基础教程系列中,已经通过<Spring Boot中使用@Async实现异步调用>一文介绍过如何使用@Async注解来实现异步调用了.但是,对于这些异步执行的控制是我们保障自身应用健康的基本技能.本文我们就来学习一下,如果通过自定义线程池的方式来控制异步调用的并发. 本文中的例子我们可以在之前的例子基础上修改,也可以创建一个全新的Spring Boot项目来尝试. 定义线程池 第一步,先在Spring Boot主类中定义一个线程池,比如: @SpringBoo

  • Spring boot注解@Async线程池实例详解

    这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行. 1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent

  • @Async异步线程池以及线程的命名方式

    本文记录@Async的基本使用以及通过实现ThreadFactory来实现对线程的命名. @Async的基本使用 近日有一个道友提出到一个问题,大意如下: 业务场景需要进行批量更新,已有数据id主键.更新的状态.单条更新性能太慢,所以使用in进行批量更新.但是会导致锁表使得其他业务无法访问该表,in的量级太低又导致性能太慢. 龙道友提出了一个解决方案,把要处理的数据分成几个list之后使用多线程进行数据更新.提到多线程可直接使用@Async注解来进行异步操作. 好的,接下来上面的问题我们不予解答

  • Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解

    目录 前言 一.创建一个Springboot Web项目 二.新建ThreadPoolConfig 三.新建controller测试 四.演示结果 前言 众所周知,创建显示线程和直接使用未配置的线程池创建线程,都会被阿里的大佬给diss,所以我们要规范的创建线程. 至于 @Async 异步任务的用处是不想等待方法执行完就返回结果,提高软件前台响应速度,一个程序中会用到很多异步方法,所以需要使用线程池管理,防止影响性能. 一.创建一个Springboot Web项目 需要一个Springboot项

  • Java concurrency线程池之线程池原理(一)_动力节点Java学院整理

    ThreadPoolExecutor简介 ThreadPoolExecutor是线程池类.对于线程池,可以通俗的将它理解为"存放一定数量线程的一个线程集合.线程池允许若个线程同时允许,允许同时运行的线程数量就是线程池的容量:当添加的到线程池中的线程超过它的容量时,会有一部分线程阻塞等待.线程池会通过相应的调度策略和拒绝策略,对添加到线程池中的线程进行管理." ThreadPoolExecutor数据结构 ThreadPoolExecutor的数据结构如下图所示: 各个数据在Thread

  • Java concurrency线程池之线程池原理(二)_动力节点Java学院整理

    线程池示例 在分析线程池之前,先看一个简单的线程池示例. import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolDemo1 { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThre

  • Java concurrency线程池之线程池原理(四)_动力节点Java学院整理

    拒绝策略介绍 线程池的拒绝策略,是指当任务添加到线程池中被拒绝,而采取的处理措施. 当任务添加到线程池中之所以被拒绝,可能是由于:第一,线程池异常关闭.第二,任务数量超过线程池的最大限制. 线程池共包括4种拒绝策略,它们分别是:AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy和DiscardPolicy. AbortPolicy         -- 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException

  • python自定义线程池控制线程数量的示例

    1.自定义线程池 import threading import Queue import time queue = Queue.Queue() def put_data_in_queue(): for i in xrange(10): queue.put(i) class MyThread(threading.Thread): def run(self): while not queue.empty(): sleep_times = queue.get() time.sleep(sleep_t

  • Java 自定义线程池和线程总数控制操作

    1 概述 池化是常见的思想,线程池是非常典型的池化的实现,<Java并发编程实战>也大篇幅去讲解了Java中的线程池.本文实现一个简单的线程池. 2 核心类 [1]接口定义 public interface IThreadPool<Job extends Runnable> { /** * 关闭线程池 */ public void shutAlldown(); /** * 执行任务 * * @param job 任务 */ public void execute(Job job);

  • Java线程池复用线程的秘密你知道吗

    目录 前言 源码探究 execute方法 addWorker方法 Worker类 实现了Runnable接口 重要属性 构造方法 run方法 执行流程 总结 前言 我们都知道线程池可以帮我们管理线程,重复利用线程执行不同的任务.正常情况下,我们创建的线程执行完任务后就会自行销毁,那么线程池是如何做到复用线程的呢? 源码探究 我们从线程池ThreadPoolExecutor源码入手,一探究竟.为了突出重点,以下的方法源码过滤了部分无关代码,以求逻辑清晰. execute方法 那就从线程池执行的ex

  • Python实现线程池之线程安全队列

    目录 一.线程池组成 二.线程安全队列的实现 三.测试逻辑 3.1.测试阻塞逻辑 3.2.测试读写加锁逻辑 本文实例为大家分享了Python实现线程池之线程安全队列的具体代码,供大家参考,具体内容如下 一.线程池组成 一个完整的线程池由下面几部分组成,线程安全队列.任务对象.线程处理对象.线程池对象.其中一个线程安全的队列是实现线程池和任务队列的基础,本节我们通过threading包中的互斥量threading.Lock()和条件变量threading.Condition()来实现一个简单的.读

  • java线程池的四种创建方式详细分析

    目录 前言 1. 线程池 2. 创建方式 前言 在讲述线程池的前提 先补充一下连接池的定义 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用 可以看到其连接池的作用如下: 1. 线程池 线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线程的代价.线程池不仅能够保证内核的充分利用,还能防止过分调度 特点:

随机推荐