返回顶部
首页 > 资讯 > 后端开发 > Python >@Async异步线程池以及线程的命名方式
  • 382
分享到

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

2024-04-02 19:04:59 382人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

本文记录@Async的基本使用以及通过实现ThreadFactory来实现对线程的命名。 @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异常在之后会说明。代码如下:



@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.有参有返回值方法

具体代码如下:



@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,现在该做的准备工作都已完成,加个测试方法看看结果如何



@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毫秒

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

--结束END--

本文标题: @Async异步线程池以及线程的命名方式

本文链接: https://lsjlt.com/news/128001.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • @Async异步线程池以及线程的命名方式
    本文记录@Async的基本使用以及通过实现ThreadFactory来实现对线程的命名。 @Async的基本使用 近日有一个道友提出到一个问题,大意如下: 业务场景需要进行批量更新,...
    99+
    2024-04-02
  • Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解
    目录前言一、创建一个Springboot Web项目二、新建ThreadPoolConfig三、新建controller测试四、演示结果前言 众所周知,创建显示线程和直接使用未配置的...
    99+
    2024-04-02
  • SpringBoot异步使用@Async的原理以及线程池配置详解
    目录前言 使用步骤 配置线程池类参数配置 自定义线程任务 总结 原理刨析 文章参考 前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以...
    99+
    2024-04-02
  • Spring Boot之@Async异步线程池示例详解
    目录前言一. Spring异步线程池的接口类 :TaskExecutor二、简单使用说明三、定义通用线程池1、定义线程池2、异步方法使用线程池3、通过xml配置定义线程池四、异常处理...
    99+
    2024-04-02
  • 浅谈Spring @Async异步线程池用法总结
    本文介绍了Spring @Async异步线程池用法总结,分享给大家,希望对大家有帮助1. TaskExecutorspring异步线程池的接口类,其实质是Java.util.concurrent.ExecutorSpring 已经实现的异常...
    99+
    2023-05-31
    async spring 线程池
  • Spring使用ThreadPoolTaskExecutor自定义线程池及异步调用方式
    目录一、ThreadPoolTaskExecutor1、将线程池用到的参数定义到配置文件中2、Executors的工厂配置2.1、配置详情2.2、注解说明2.3、线程池配置说明2.4...
    99+
    2024-04-02
  • 详解Java如何关闭线程以及线程池
    目录前言1. 关闭线程1.1 volatile关键字1.2 intrrrupt()方法2.关闭线程池2.1 shutdownNow()方法2.2 shutdown()方法前言 这个问...
    99+
    2024-04-02
  • 线程池的实现方式
    线程池有以下几种实现方式:Executors目前提供了5种不同的线程池创建配置:1、newCachedThreadPool()它是用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的...
    99+
    2018-03-19
    java入门 线程池
  • PHP中的线程池和异步编程实践
    近年来,PHP 开发者们开发出许多并发编程的技术,其中又以线程池和异步编程应用最为广泛。本文将介绍线程池和异步编程的基本概念以及它们在 PHP 中的实践应用。 一、线程池的概念线程池是一种并发编程领域中常见的技术。它是由一组线程组成的线程集...
    99+
    2023-05-23
    线程池 异步编程 PHP
  • Python异步爬虫多线程与线程池示例详解
    目录背景异步爬虫方式多线程,多进程(不建议)线程池,进程池(适当使用)单线程+异步协程(推荐)多线程线程池背景 当对多个url发送请求时,只有请求完第一个url才会接着请求第二个ur...
    99+
    2024-04-02
  • Java的线程与进程以及线程的四种创建方式
    目录问题描述case 代码截图数据库DOcontroller定义dao定义mapper实现mysql相关 properties配置数据库数据测试结果具体错误信息解决总结问题描述 这里...
    99+
    2024-04-02
  • java线程池的实现原理、优点与风险、以及4种线程池实现
    为什么需要线程池 我们有两种常见的创建线程的方法,一种是继承Thread类,一种是实现Runnable的接口,Thread类其实也是实现了Runnable接口。但是我们创建这两种线程...
    99+
    2023-02-18
    java 线程池的实现原理 java 线程池优点与风险 java 4种线程池实现 java 配置线程池大小配置 java 线程池的实现原理
  • 线程以及多线程,多进程的选择
    我的理解是进程是指在系统中正在运行的一个应用程序;程序一旦运行就是进程,或者更专业化来说:进程是指程序执行时的一个实例,线程是进程的一个实体。进程——资源分配的最小单位,线程——程序执行的最小单位。线程进程的区别体现在几个方面:...
    99+
    2023-06-04
  • 线程池的创建方式有哪些
    这篇文章主要讲解了“线程池的创建方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“线程池的创建方式有哪些”吧!什么是线程池线程池(ThreadPool...
    99+
    2024-04-02
  • java线程池合理设置最大线程数和核心线程数方式
    目录线程池合理设置最大线程数和核心线程数一开始是这么配置的后来网上查询线程池核心数配置最后我是这么配置的线程池核心线程数与最大线程数的区别线程池策略饱和策略线程池合理设置最大线程数和...
    99+
    2024-04-02
  • Java线程池的本质以及作用是什么
    Java线程池的本质以及作用是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。熟悉java多线程的 朋友一定十分了解java的线程池,jdk中的核心实现类为j...
    99+
    2023-06-17
  • java 实现开启异步线程的几种方式
    在Java中,有多种方式可以实现异步线程以避免在主线程中执行耗时操作导致界面卡顿的问题。以下是几种常用的方式: 使用Thread类:可以使用Thread类来创建一个新的线程,并在其run()方法中执行耗时操作。例如: new Thread(...
    99+
    2023-08-17
    java
  • Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用
    这篇文章主要介绍了Spring中怎么使用ThreadPoolTaskExecutor自定义线程池及异步调用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring中怎么使用ThreadPoolTaskExec...
    99+
    2023-06-29
  • Python多线程以及多线程中join()的使用方法
    本篇内容主要讲解“Python多线程以及多线程中join()的使用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python多线程以及多线程中join()的使用方法”吧!Python多线程与...
    99+
    2023-06-20
  • Python Django 协程报错,进程池、线程池与异步调用、回调机制
    在Django视图函数中,导入 gevent 模块import gevent from gevent import monkey; monkey.patch_all() ...
    99+
    2023-01-31
    报错 线程 回调
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作