在使用springboot框架开发的过程中,难免也会用到多线程业务处理的需求,如果是普通的类实现多线程,那使用我们上一篇文章中的方法就足够了。但是大部分的使用环境是是我们需要将一个注入容器的实例类实现多线程,比如业务中要操作数据库调用其他方法等都难免要引用其他的实例。但是spring中的实例默认是单例的,针对这种情况我们应该怎么实现多线程呢,下面给大家用demo详细解释一下:

    在spring的项目中,由于Bean对象是spring容器管理的,你直接new出来的对象是没法使用的,就算你能new成功,但是bean里面依赖的其他组件比如Dao,是没法初始化的,因为你饶过了spring,默认的spring初始化一个类时,其相关依赖的组件都会被初始化,但是自己new出来的类,是不具备这种功能的,所以我们需要通过spring来获取我们自己的线程类,那么如何通过spring获取类实例呢,需要定义如下的一个类来获取:

 

package com.ganinfo.provider;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.provider
 * @className:
 * @description:
 * @date 2018-10-30 11:14
 **/
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext context;


    private ApplicationContextProvider() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(String name, Class<T> aClass) {
        return context.getBean(name, aClass);
    }


}


然后写我们自己业务逻辑需要的线程类,注意此类是原型作用域,不能是默认的单例:

package com.ganinfo.test;

import com.ganinfo.deviceauth.pojo.AuthBindPO;
import com.ganinfo.dic.mapper.DicMapper;
import com.ganinfo.utils.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.concurrent.Callable;

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.test
 * @className:
 * @description:
 * @date 2018-10-28 19:35
 **/
@Slf4j
@Component
@Scope("prototype")
public class AuthCallable implements Callable {
    @Autowired
    private DicMapper dicMapper;

    private AuthBindPO authBindPO;
    public AuthBindPO getAuthBindPO() {
        return authBindPO;
    }

    public void setAuthBindPO(AuthBindPO authBindPO) {
        this.authBindPO = authBindPO;
    }

    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    @Override
    public Object call() throws Exception {
        log.info("参数"+ GsonUtil.GsonString(authBindPO));
        dicMapper.getDicList(null);
        if ("1".equals(authBindPO.getAuthType())){
            log.info("方式一"+authBindPO.getDeviceName()+"授权start");
//            Thread.sleep(8000);
            log.info("方式一授权end");
            return authBindPO.getDeviceName();
        }
        if ("2".equals(authBindPO.getAuthType())){
            log.info("方式二"+authBindPO.getDeviceName()+"授权start");
//            Thread.sleep(7000);
            log.info("方式二授权end");
            return authBindPO.getDeviceName();
        }
        if ("3".equals(authBindPO.getAuthType())){
            log.info("方式三"+authBindPO.getDeviceName()+"授权start");
//            Thread.sleep(5000);
            log.info("方式三授权end");
            return authBindPO.getDeviceName();
        }
        if ("4".equals(authBindPO.getAuthType())){
            log.info("方式四"+authBindPO.getDeviceName()+"授权start");
//            Thread.sleep(3000);
            log.info("方式四授权end");
            return authBindPO.getDeviceName();
        }
        if ("5".equals(authBindPO.getAuthType())){
            log.info("方式五"+authBindPO.getDeviceName()+"授权start");
//            Thread.sleep(1000);
            log.info("方式五授权end");
            return authBindPO.getDeviceName();
        }

        return null;
    }


}

调用多线程的方法:

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.test
 * @className:
 * @description:
 * @date 2018-10-28 19:41
 **/
@Service
@Slf4j
public class AuthService {
//    @Autowired
//    private AuthCallable authCallable;

    public void auth(String a) {
        long start=System.currentTimeMillis();
        List<String> list = new ArrayList<>();
        int count=5;
        try {

            List<AuthBindPO> list1=new ArrayList<>();
            String a1="{\"deviceModel\":\"haikang\",\"deviceId\":\"213688264\",\"authId\":\"52EE8849\",\"deviceURL\":\"223.223.176.210:20055\",\"idNumber\":\"329\",\"name\":\"王\",\"sex\":\"1\",\"nation\":\"01\",\"birth\":\"199\",\"address\":\"哈尔号\",\"phone\":\"13121205711\",\"authType\":\"1\",\"createUser\":\"58b815af9c794b83a63d8f5660c2e567\",\"deviceName\":\"海康测试——154\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"code\":\"6044e44eedd041c0aca0cf48fcda91af\",\"placeCode\":\"650106001001010009\",\"placeName\":\"小区\",\"telephone\":\"13121205711\",\"authDeviceDO\":{\"authDeviceCode\":\"a0656e6b-8e7d-42c7-9d31-5f072c3632db\",\"deviceId\":\"213688264\",\"deviceModel\":\"haikang\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"ip\":\"223.223.176.210\",\"port\":\"20055\",\"deviceDoorName\":\"海康测试——154\",\"code\":\"30abaca6aac449fcb314c90971c1d5a9\",\"is_delete\":0,\"create_time\":\"Oct 30, 2018 2:11:36 PM\",\"create_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"update_time\":\"Oct 30, 2018 2:11:36 PM\",\"update_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"remark\":\"无\"}}";
            list1.add(GsonUtil.GsonToBean(a1,AuthBindPO.class));
            String a2="{\"deviceModel\":\"haikang\",\"deviceId\":\"211856639\",\"authId\":\"52EE8849\",\"deviceURL\":\"223.223.176.210:20053\",\"idNumber\":\"39\",\"name\":\"王\",\"sex\":\"1\",\"nation\":\"01\",\"birth\":\"107\",\"address\":\"哈尔滨\",\"phone\":\"13121205711\",\"authType\":\"2\",\"createUser\":\"58b815af9c794b83a63d8f5660c2e567\",\"deviceName\":\"海康测试172\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"code\":\"6044e44eedd041c0aca0cf48fcda91af\",\"placeCode\":\"650106001001010009\",\"placeName\":\"孝感路幸福小区\",\"telephone\":\"13121205711\",\"authDeviceDO\":{\"authDeviceCode\":\"f10a95b0-a63d-4c57-929d-882ea229e98d\",\"deviceId\":\"211856639\",\"deviceModel\":\"haikang\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"ip\":\"223.223.176.210\",\"port\":\"20053\",\"deviceDoorName\":\"海康测试172\",\"code\":\"609f915ffd22483e81088cf603dc62b0\",\"is_delete\":0,\"create_time\":\"Oct 30, 2018 2:11:36 PM\",\"create_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"update_time\":\"Oct 30, 2018 2:11:36 PM\",\"update_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"remark\":\"无\"}}";
            list1.add(GsonUtil.GsonToBean(a2,AuthBindPO.class));
            String a3="{\"deviceModel\":\"haikang\",\"deviceId\":\"57668758\",\"authId\":\"52EE8849\",\"deviceURL\":\"10.1.201.1:2647\",\"idNumber\":\"39\",\"name\":\"王\",\"sex\":\"1\",\"nation\":\"01\",\"birth\":\"1907\",\"address\":\"哈\",\"phone\":\"13121205711\",\"authType\":\"3\",\"createUser\":\"58b815af9c794b83a63d8f5660c2e567\",\"deviceName\":\"海康测试1024\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"code\":\"6044e44eedd041c0aca0cf48fcda91af\",\"placeCode\":\"650106001001010009\",\"placeName\":\"孝感路幸福小区\",\"telephone\":\"13121205711\",\"authDeviceDO\":{\"authDeviceCode\":\"8c019494-0535-4b2e-a6f3-082272397614\",\"deviceId\":\"57668758\",\"deviceModel\":\"haikang\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"ip\":\"10.1.201.1\",\"port\":\"2647\",\"deviceDoorName\":\"海康测试1024\",\"code\":\"15afb0a6b54b43369a14bfbce0160612\",\"is_delete\":0,\"create_time\":\"Oct 30, 2018 2:11:36 PM\",\"create_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"update_time\":\"Oct 30, 2018 2:11:36 PM\",\"update_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"remark\":\"无\"}}";
            list1.add(GsonUtil.GsonToBean(a3,AuthBindPO.class));
            String a4="{\"deviceModel\":\"haikang\",\"deviceId\":\"876698769878\",\"authId\":\"52EE8849\",\"deviceURL\":\"10.1.20.1:1234\",\"idNumber\":\"324\",\"name\":\"王钰\",\"sex\":\"1\",\"nation\":\"01\",\"birth\":\"1993-08-07\",\"address\":\"哈尔\",\"phone\":\"13121205711\",\"authType\":\"4\",\"createUser\":\"58b815af9c794b83a63d8f5660c2e567\",\"deviceName\":\"测试多线程1\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"code\":\"6044e44eedd041c0aca0cf48fcda91af\",\"placeCode\":\"650106001001010009\",\"placeName\":\"孝感路幸福小区\",\"telephone\":\"13121205711\",\"authDeviceDO\":{\"authDeviceCode\":\"7b2dd5e2-4758-43c7-b2a6-e962c98891a4\",\"deviceId\":\"876698769878\",\"deviceModel\":\"haikang\",\"authCode\":\"8f1dbbd10736422bab7340bffef61e9a\",\"ip\":\"10.1.20.1\",\"port\":\"1234\",\"deviceDoorName\":\"测试多线程1\",\"code\":\"4b5831139f534940a16f9fe6af28ea18\",\"is_delete\":0,\"create_time\":\"Oct 30, 2018 2:11:36 PM\",\"create_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"update_time\":\"Oct 30, 2018 2:11:36 PM\",\"update_user\":\"58b815af9c794b83a63d8f5660c2e567\",\"remark\":\"无\"}}";
            list1.add(GsonUtil.GsonToBean(a4,AuthBindPO.class));
            final CountDownLatch countDownLatch = new CountDownLatch(list1.size());
            ExecutorService executorService = Executors.newFixedThreadPool(8);
            ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
            for (AuthBindPO va:list1) {
//                AuthCallable authCallable = new AuthCallable();
                AuthCallable authCallable= ApplicationContextProvider.getBean("authCallable", AuthCallable.class);
                AuthBindPO authBindPO=va;
                authCallable.setAuthBindPO(authBindPO);
                ListenableFuture listenableFuture = listeningExecutorService.submit(authCallable);
                Futures.addCallback(listenableFuture, new FutureCallback<String>() {
                    @Override
                    public void onSuccess(String name) {
                        log.info("授权结果" + name);
                        list.add(name);
                        countDownLatch.countDown();
                    }

                    @Override
                    public void onFailure(Throwable throwable) {
                        countDownLatch.countDown();
                        log.info("处理出错:", throwable);

                    }
                });
            }
                  try {
                        executorService.shutdown();
                      //shutdown调用后,不可以再submit新的task,已经submit的将继续执行。
                        if (!countDownLatch.await(15, TimeUnit.MINUTES)) {
                            log.info("超时的时候向线程池中所有的线程发出中断");
                            // 超时的时候向线程池中所有的线程发出中断(interrupted)。
                            executorService.shutdownNow();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        executorService.shutdownNow();
                         //shutdownNow试图停止当前正执行的task,并返回尚未执行的task的list
                    }
            log.info("执行结果" + GsonUtil.GsonString(list));
            long end=System.currentTimeMillis();
            log.info("用时" + (end-start));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

 

测试方法:

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class ConControllerTest {
    @Autowired
    private ConController conController;
    @Autowired
    private AuthService authService;
    @Test
    public void test1() throws Exception {
//        conController.test1();
        authService.auth(null);

}

}

运行以后和上一篇文章的执行结果是相同的。业务代码中最关键的是多线程类的实例化方式:

 AuthCallable authCallable= ApplicationContextProvider.getBean("authCallable", AuthCallable.class);
 
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐