• 关于Java串行、并行执行——使用Callable多线程


    一.使用Callable多线程:

    通过Callable接口实现多线程

    实现Callable重写call方法;

    实现Callable和实现Runnable类似,但是功能更强大,具体表现在:

    a.可以在任务结束后提供一个返回值,Runnable不行;

    b.call方法可以抛出异常,Runnable的run方法不行;

    c.可以通过运行Callable得到的Fulture对象监听目标线程调用call方法的结果,得到返回值,(fulture.get(),调用后会阻塞,直到获取到返回值);

    1Callable接口介绍:

    (1)java.util.concurrent.Callable是一个泛型接口,只有一个call()方法;

    (2)call()方法抛出异常Exception异常,且返回一个指定的泛型类对象;

    2、Callable接口实现多线程的应用场景

    (1)当父线程想要获取子线程的运行结果时;

    3、使用Callable接口实现多线程的步骤

    (1)第一步:创建Callable子类的实例化对象;

    (2)第二步:创建FutureTask对象,并将Callable对象传入FutureTask的构造方法中(注意:FutureTask实现了Runnable接口和Future接口);

      (3)第三步:实例化Thread对象,并在构造方法中传入FurureTask对象;

      (4)第四步:启动线程;

    二.需求:

    做一个报表功能:在一个方法中查询多个数据库表的结果,然后汇总返回;

    由于单独查询一个数据库表速度较慢(大字段查询),此时如果串行查询多个表的话效率会非常低,所以需要多线程同时查询数据库,等全部查询完毕后再汇总!

    DAO层:

    package com.moerlong.yj.mapper;
    
    import org.apache.ibatis.annotations.Select;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface BaseMapper {
    
        @Select("select hf_industry_record from msd_hf_industry_person_srcdata where card_id = #{cardId}")
        public String selectIndustryData(String cardId);
    
        @Select("select hf_judicial_record from msd_hf_judicial_person_srcdata where card_id = #{cardId}")
        public String selectJudicialData(String cardId);
    
        @Select("select td_record from msd_td_preloan_srcdata where card_id = #{cardId}")
        public String selectTdData(String cardId);
    }

    Service层:

    串行执行:

    package com.moerlong.yj.Service;
    
    import com.moerlong.yj.mapper.BaseMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    
    @Service
    public class TestNoCallable {
    
        @Autowired
        private BaseMapper baseMapper;
    
        public String test1(String cardId) throws Exception{
            long start = System.currentTimeMillis();
    
            //三个串行查询
            String industryData = baseMapper.selectIndustryData(cardId);
            String judicialData = baseMapper.selectJudicialData(cardId);
            String tdData = baseMapper.selectTdData(cardId);
    
            Thread.sleep(3000);     //此处模拟每个查询添加1s耗时
    
            String result = industryData + judicialData + tdData;
    
            long end = System.currentTimeMillis();
            System.out.println("串行执行:" + (end-start));
    
            return result;
        }
    }

    并行执行:

    package com.moerlong.yj.Service;
    
    import com.moerlong.yj.mapper.BaseMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.lang.reflect.Method;
    import java.util.concurrent.*;
    
    
    @Service
    public class TestCallable {
        @Autowired
        private BaseMapper baseMapper;
    
        public String test2(String cardId) throws Exception{
            // 三个线程的线程池,核心线程=最大线程,没有临时线程,阻塞队列无界
            ExecutorService executorService = Executors.newFixedThreadPool(3);
    
            long start = System.currentTimeMillis();
    
            // 开启线程执行
            // 注意,此处Future对象接收线程执行结果不会阻塞,只有future.get()时候才会阻塞(直到线程执行完返回结果)
            Future future1 = executorService.submit(new SelectTask<>(this, "selectIndustryData", new Object[]{cardId}));
    
            Future future2 = executorService.submit(new SelectTask<>(this, "selectJudicialData", new Object[]{cardId}));
    
            Future future3 = executorService.submit(new SelectTask<>(this, "selectTdData", new Object[]{cardId}));
    
            //此处用循环保证三个线程执行完毕,再去拼接三个结果
            do{
                System.out.println("多任务同时执行中...");
            }while (!(future1.isDone() && future2.isDone() && future3.isDone()));
    
            String result = (String)future1.get() + future2.get() + future3.get();
    
            long end = System.currentTimeMillis();
            System.out.println("并行执行:" + (end-start));
    
            return result;
    
        }
    
        //下面是三个真正执行任务(查数据库)的方法
        public String selectIndustryData(String cardId) throws Exception{
            String result = baseMapper.selectIndustryData(cardId);
            Thread.sleep(1000);    //模拟添加1s耗时
            return result;
        }
    
        public String selectJudicialData(String cardId) throws Exception{
            String result = baseMapper.selectJudicialData(cardId);
            Thread.sleep(1000);
            return result;
        }
    
        public String selectTdData(String cardId) throws Exception{
            String result = baseMapper.selectTdData(cardId);
            Thread.sleep(1000);
            return result;
        }
    
        //任务线程类
        class SelectTask<T> implements Callable<T> {
    
            private Object object;
            private Object[] args;
            private String methodName;
    
            public SelectTask(Object object, String methodName, Object[] args) {
                this.object = object;
                this.args = args;
                this.methodName = methodName;
            }
    
            @Override
            public T call() throws Exception {
                Method method = object.getClass().getMethod(methodName,String.class);   //此处应用反射机制,String.class是根据实际方法参数设置的
                return (T) method.invoke(object, args);
            }
        }
    }

    控制层:

    package com.moerlong.yj.controller;
    
    
    import com.moerlong.yj.Service.TestCallable;
    import com.moerlong.yj.Service.TestNoCallable;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    
    @RestController
    public class TestController {
    @Autowired
    private TestNoCallable testNoCallable; @Autowired private TestCallable testCallable; @RequestMapping(value = "/test1/{cardId}") public String test1(@PathVariable String cardId) throws Exception{ String result = testNoCallable.test1(cardId); return result; } @RequestMapping(value = "/test2/{cardId}") public String test2(@PathVariable String cardId) throws Exception{ String result = testCallable.test2(cardId); return result; } }
  • 相关阅读:
    # 2018-2019-1 20165206 《信息安全系统设计基础》第1周学习总结
    20165206 2017-2018-2《Java程序设计》课程总结
    2017-2018-2 20165206 实验五《网络编程与安全》实验报告
    20165206第4次实验《Android程序设计》实验报告
    同源策略、跨域解决方案
    盒子模型,块级元素和行内元素
    http常见错误
    深入理解 JavaScript 事件循环(一)— event loop
    git常用指令
    js 常用方法
  • 原文地址:https://www.cnblogs.com/ZJOE80/p/12131045.html
Copyright © 2020-2023  润新知