Spring Boot实践——多线程

摘要:
importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;
多线程

  Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以我们要在配置类中通过@EnableAsync开启对异步任务的支持,并通过在实际执行的Bean的方法中使用@Async注解声明其是一个异步任务。

  此外,还提供一种Java的实现方式,多种方式去尝试如何去实现多线程。

实现

一、基于Spring

1、配置类

import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * @Description: 配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreadPoolTaskExecutor,
 * 这样我们就获得一个基于线程池TaskExecutor
 * @ClassName: CustomMultiThreadingConfig
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午2:50:14
 */
@Configuration
@ComponentScan("com.only.mate.springboot.multithreading")
@EnableAsync//利用@EnableAsync注解开启异步任务支持
public class CustomMultiThreadingConfig implements AsyncConfigurer{

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
    }
    
}

2、创建线程任务

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @Description: 创建线程任务服务
 * @ClassName: CustomMultiThreadingService
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:17:57
 */
@Service
public class CustomMultiThreadingService {
    private Logger logger = LoggerFactory.getLogger(CustomMultiThreadingService.class);
    /**
     * @Description:通过@Async注解表明该方法是一个异步方法,
     * 如果注解在类级别上,则表明该类所有的方法都是异步方法,而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAysncTask1
     * @Date: 2018年9月21日 下午2:54:32
     * @Author: OnlyMate
     * @Throws
     * @param i
     */
    @Async
    public void executeAysncTask1(Integer i){
        logger.info("CustomMultiThreadingService ==> executeAysncTask1 method: 执行异步任务{} ", i);
    }
    
    /**
     * @Description:通过@Async注解表明该方法是一个异步方法,
     * 如果注解在类级别上,则表明该类所有的方法都是异步方法,而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAsyncTask2
     * @Date: 2018年9月21日 下午2:55:04
     * @Author: OnlyMate
     * @Throws
     * @param i
     */
    @Async
    public void executeAsyncTask2(Integer i){
        logger.info("CustomMultiThreadingService ==> executeAsyncTask2 method: 执行异步任务{} ", i);
    }
}

3、触发线程任务

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.only.mate.springboot.multithreading.CustomMultiThreadingService;

/**
 * @Description:自定义多线程Controller
 * @ClassName: CustomMultiThreadingController
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:02:49
 */
@Controller
@RequestMapping(value="/multithreading")
public class CustomMultiThreadingController {
    @Autowired
    private CustomMultiThreadingService customMultiThreadingService;
    
    @ResponseBody
    @RequestMapping(value="/dotask")
    public String doTask() {
        for (int i=0;i<10;i++){
            customMultiThreadingService.executeAysncTask1(i);
            customMultiThreadingService.executeAsyncTask2(i);
        }
        
        return "success";
    }
}

4、效果图

访问http://localhost:8088/springboot/multithreading/dotask

Spring Boot实践——多线程第1张

 二、基于Java

1、异步线程调度管理器

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 异步线程调度管理器
 * @ClassName: CustomAsyncScheduler
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:25:40
 */
public class CustomAsyncScheduler {
    private volatile static CustomAsyncScheduler instance;
    private static ThreadPoolExecutor chnlBackendQueryPool;

    private CustomAsyncScheduler() {
    }

    @SuppressWarnings({ "rawtypes", "static-access", "unchecked" })
    public static CustomAsyncScheduler getInstance() {
        if (instance == null) {
            synchronized (CustomAsyncScheduler.class) {
                if (instance == null) {
                    instance = new CustomAsyncScheduler();

                    BlockingQueue queue = new LinkedBlockingQueue();
                    chnlBackendQueryPool = new ThreadPoolExecutor(50, 100, 30, TimeUnit.SECONDS, queue);
                    chnlBackendQueryPool.allowCoreThreadTimeOut(true);
                    instance.setChnlBackendQueryPool(chnlBackendQueryPool);
                }
            }
        }
        return instance;
    }

    public ThreadPoolExecutor getChnlBackendQueryPool() {
        return chnlBackendQueryPool;
    }

    public static void setChnlBackendQueryPool(ThreadPoolExecutor chnlBackendQueryPool) {
        CustomAsyncScheduler.chnlBackendQueryPool = chnlBackendQueryPool;
    }

    public static void setInstance(CustomAsyncScheduler instance) {
        CustomAsyncScheduler.instance = instance;
    }

}

2、创建线程任务

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @Description: 创建线程任务服务
 * @ClassName: CustomMultiThreadingService
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:17:57
 */
@Service
public class CustomMultiThreadingService {
    private Logger logger = LoggerFactory.getLogger(CustomMultiThreadingService.class);
    /**
     * @Description:通过@Async注解表明该方法是一个异步方法,
     * 如果注解在类级别上,则表明该类所有的方法都是异步方法,而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAysncTask1
     * @Date: 2018年9月21日 下午2:54:32
     * @Author: OnlyMate
     * @Throws
     * @param i
     */
    @Async
    public void executeAysncTask1(Integer i){
        logger.info("CustomMultiThreadingService ==> executeAysncTask1 method: 执行异步任务{} ", i);
    }
    
    /**
     * @Description:通过@Async注解表明该方法是一个异步方法,
     * 如果注解在类级别上,则表明该类所有的方法都是异步方法,而这里的方法自动被注入使用ThreadPoolTaskExecutor作为TaskExecutor
     * @Title: executeAsyncTask2
     * @Date: 2018年9月21日 下午2:55:04
     * @Author: OnlyMate
     * @Throws
     * @param i
     */
    @Async
    public void executeAsyncTask2(Integer i){
        logger.info("CustomMultiThreadingService ==> executeAsyncTask2 method: 执行异步任务{} ", i);
    }
    
    /**
     * @Description: 异步线程调度管理器创建线程任务
     * @Title: executeAsyncTask3
     * @Date: 2018年9月21日 下午3:32:28
     * @Author: OnlyMate
     * @Throws
     * @param i
     */
    public void executeAsyncTask3(Integer i){
        CustomAsyncScheduler.getInstance().getChnlBackendQueryPool().execute(new Runnable() {
            @Override
            public void run() {
                logger.info("CustomMultiThreadingService ==> executeAsyncTask3 method: 执行异步任务{} ", i);                
            }
        });
        
    }
}

3、触发线程任务

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.only.mate.springboot.multithreading.CustomMultiThreadingService;

/**
 * @Description:自定义多线程Controller
 * @ClassName: CustomMultiThreadingController
 * @Author: OnlyMate
 * @Date: 2018年9月21日 下午3:02:49
 */
@Controller
@RequestMapping(value="/multithreading")
public class CustomMultiThreadingController {
    @Autowired
    private CustomMultiThreadingService customMultiThreadingService;
    
    @ResponseBody
    @RequestMapping(value="/dotask")
    public String doTask() {
        for (int i=0;i<10;i++){
            customMultiThreadingService.executeAysncTask1(i);
            customMultiThreadingService.executeAsyncTask2(i);
        }
        
        return "success";
    }
    
    @ResponseBody
    @RequestMapping(value="/dojob")
    public String doJob() {
        for (int i=0;i<10;i++){
            customMultiThreadingService.executeAysncTask1(i);
            customMultiThreadingService.executeAsyncTask2(i);
            customMultiThreadingService.executeAsyncTask3(i);
        }
        return "success";
    }
}

4、效果图

访问http://localhost:8088/springboot/multithreading/dojob

Spring Boot实践——多线程第2张

免责声明:文章转载自《Spring Boot实践——多线程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vue.js click点击事件获取当前元素对象Java并发(6):concurrent包中的Copy-On-Write容器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

多线程(一)java并发编程基础知识

线程的应用 如何应用多线程 在 Java 中,有多种方式来实现多线程。继承 Thread 类、实现 Runnable 接口、使用 ExecutorService、Callable、Future 实现带返回结果的多线程。 继承 Thread 类创建线程 Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。启动线程的唯一方法就...

Python 并发编程(一)之线程

常用用法 t.is_alive() Python中线程会在一个单独的系统级别线程中执行(比如一个POSIX线程或者一个Windows线程)这些线程将由操作系统来全权管理。线程一旦启动,将独立执行直到目标函数返回。可以通过查询一个线程对象的状态,看它是否还在执行t.is_alive() t.join() 可以把一个线程加入到当前线程,并等待它终止Python...

数量线程SM,SP和GRID,BLOCK,THREAD之间的对应关系是什么?

最近应用开发的过程中出现了一个小问题,顺便记录一下原因和方法--数量线程     SM,SP是硬件构结          GRID,BLOCK,THREAD是软件念概                    从硬件度角讲,一个GPU由多个SM构成(当然还有其他部份),一个SM含包有多个SP(以及还有寄存器资源,shared memory资源,L1cache,...

2个线程 循环打印ababab...

第一种方式: package mianshi.Thread; /** * 2个线程 循环打印 abab * 实现1: * note: 2个线程操作 Work类, work类里面 实现互斥的 2个打印方法 A B。 2个线程各自调用A,B */ public class ThreadA { public static void main(...

JS的"多线程"

这个系列的文章名为“JavaScript 进阶”,内容涉及JS中容易忽略但是很有用的,偏JS底层的,以及复杂项目中的JS的实践。主要来源于我几年的开发过程中遇到的问题。小弟第一次写博客,写的不好的地方请诸位斧正,觉得还有一些阅读价值的请帮忙分享下。这个“JavaScript 进阶”是一个系列文章,请大家鼓励鼓励,我尽快更新。另外,如果你有比较好的话题,也可...

java守护线程

守护线程: 线程分为用户线程和守护线程,当用户线程执行完毕后,程序就会结束,JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态 ,后台线程就是用来服务其他线程的线程,thread.setDaemon(true)必须在thread.start()之前设置; 执行情况: 主线程(main)执行结束后,用户线程可以继续执行直至执行完...