精华内容
下载资源
问答
  • 多线程查询

    千次阅读 2017-05-31 23:47:20
    今天遇到下载资金流水记录的场景。...下面示例展示了采用Callable和Future进行多线程查询并使用CountDownLatch进行多线程同步。// 进行首次查询(略),获取总页数 int totalPage; // 设置计数器,从0开始 final Coun

    今天遇到下载资金流水记录的场景。下载的数据源于分页查询,一次5000条。当数据量到达十万级的时候,仅仅通过for循环、每次设置pageNum,查询的等待时间超过了容忍的范围。下面示例展示了采用Callable和Future进行多线程查询并使用CountDownLatch进行多线程同步。

    // 进行首次查询(略),获取总页数
    int totalPage;
    // 设置计数器,从0开始
    final CountDownLatch countDownLatch = new CountDownLatch(totalPage - 1);
    // 定义Future数组,数组大小和计数器个数相同
    Future<PageResult<FundRecordDTO>>[] futures = new Future[totalPage - 1];
    for (int i = 0; i < totalPage; i++) {
        // 重设分页参数,从1开始
        final PageArg pageArg = new PageArg();
        pageArg.setPageSize(ExcelHelper.pageSize);
        pageArg.setPageIndex(i + 1);
        // 将各个PageResult塞到线程池的各个线程里,返回Future数组
        futures[i] = threadPool.submit(new Callable<PageResult<FundRecordDTO>>() {
            // 返回取得的PageResult
            @Override
            public PageResult<FundRecordDTO> call() throws Exception {
                PageResult<FundRecordDTO> pageResult = new PageResult<FundRecordDTO>();
                try {
                    pageResult = fundRecordService.findFundRecordPage(pageArg, fundRecordParam);
                } catch (Exception e) {
                    throw e;
                } finally {
                    // 线程完成任务后通过countDownLatch.countDown()来通知CountDownLatch对象,计数器-1
                    countDownLatch.countDown();
                }
                return pageResult;
            }
        });
    }
    // 所有任务执行完毕后触发事件,唤醒await在latch上的主线程
    countDownLatch.await();
    // 合并记录
    for (int j = 0; j < totalPage; j++) {
        if (futures[j] != null && futures[j].get().getData() != null) {
            fileDataList.addAll(futures[j].get().getData());
        }
    }

    上面的例子用到了Callable、Future和CountDownLatch三个常用的多线程工具类,下面我们分别来了解下。

    Callable和Future

    Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务。

    Callable和Runnable的区别如下:

    • Callable定义的方法是call,而Runnable定义的方法是run。
    • Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
    • Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。
        public
        interface Runnable {
            /**
             * When an object implementing interface <code>Runnable</code> is used
             * to create a thread, starting the thread causes the object's
             * <code>run</code> method to be called in that separately executing
             * thread.
             * <p>
             * The general contract of the method <code>run</code> is that it may
             * take any action whatsoever.
             *
             * @see     java.lang.Thread#run()
             */
            public abstract void run();
        }
        public interface Callable<V> {  
            /** 
             * Computes a result, or throws an exception if unable to do so. 
             * 
             * @return computed result 
             * @throws Exception if unable to compute a result 
             */  
            V call() throws Exception;  
        }  

    Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。

    public interface Future<V> {  
        // 可以取消任务的执行,参数为true表示立即中断任务的执行,参数为false表示允许正在运行的任务运行完成。
        boolean cancel(boolean mayInterruptIfRunning);  
    
        // 查询是否取消掉  
        boolean isCancelled();  
    
        // 查询是否完成
        boolean isDone();  
    
        // 等待计算完成,获取计算结果。  
        V get() throws InterruptedException, ExecutionException;  
    
        // 在超时时间内等待计算完成,获取计算结果。 
        V get(long timeout, TimeUnit unit)  
            throws InterruptedException, ExecutionException, TimeoutException;  
    } 

    CountDownLatch

    CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。

    和其它并发工具类,如CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下。

    CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。这个初始值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
    countDownLatch.countDown

    与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。

    展开全文
  • 易语言多线程查询源码,多线程查询,查询,UTF8转Unicode,Unicode转Ansi,UTF8解码,系统时间,系统时间到毫秒,API_MultiByteToWideChar,API_WideCharToMultiByte
  • 易语言多线程查询域名源码,多线程查询域名,开始查询,查询线程,域名查询,整理域名,随机生成域名,准备查询,挂起线程,恢复线程,创建线程,销毁线程
  • 主要介绍了python使用多线程查询数据库的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 需求中需要查询多个SQL...但是使用并行的方式进行查询,即多线程查询,所消耗的时间为查询最久SQL的时间。 此处使用callable + furtherTask 方式实现 Callable<List<Map<String, String>>> ma...

    需求中需要查询多个SQL结果,且这些结果间没有相互联系。

    正常情况下使用串行的方式进行查询,所消耗的时间为所有SQL查询的时间之和,

    但是使用并行的方式进行查询,即多线程查询,所消耗的时间为查询最久SQL的时间。

    此处使用callable + furtherTask 方式实现

    Callable<List<Map<String, String>>> mainCall = new Callable<List<Map<String, String>>>(){
    	@Override
    	public List<Map<String, String>> call() throws Exception {
    		//创建DBConnection,可以创建在外部,但需要使用final关键字
    		DBConnection dbc = DataSource.getDBConnection("odsm");
    		//平台封装方法,创建查询,此处注意需要每次new一个DBQuery,否则仍然是串行执行,
            //猜测一个DBQuery同一时间只能执行一个查询,此处DBQuery仅针对我个人使用的平台。
    		DBQuery dbq = new DBQuery(dbc);
    		//查询结果存储在list内
    		List<Map<String, String>> list = dbq.query("TEMP_WY.queryMain", map);
    		//返回查询结果
    		return list;
    	}
    };

    创建一个FutureTask用于存放查询后的结果,在Thread执行后通过get获取

    FutureTask<List<Map<String, String>>> mainFuture = new FutureTask<List<Map<String, String>>>(mainCall);
    new Thread(mainFuture).start();
    //FutureTask的get方法是线程阻塞的,必须要等待线程都执行完成后,才能获取到结果
    List<Map<String, String>> mainList = mainFuture.get();

    以上是一个线程的创建、执行、获取方法。

    多个线程即重复以上定义即可。

    另外建议根据SQL查询来放置线程顺序,我有两个线程都涉及复杂的查询,且用到同几个表:关联、子查询、汇总等,原来将两个放在7与8的位置,导致同一时间同一资源占用较大,通常第8个查询需要20s才能让出结果,将两个一个放在第一个线程执行,一个放在最后一个线程执行,虽然是并发执行,但执行速度明显加快。

    展开全文
  • GreenDao多线程查询

    千次阅读 2018-07-22 20:45:07
    特别是多线程中,因为他在多线程查询中,在每个线程中定义一个属于当前线程的查询对象,这样子每个线程之间都互相不干扰,比对对象加锁进行同步操作的性能提高了很多,节省了加锁的开销。   先用最普通的方法在...

    GreenDao号称最快的ORM数据操作。特别是多线程中,因为他在多线程查询中,在每个线程中定义一个属于当前线程的查询对象,这样子每个线程之间都互相不干扰,比对对象加锁进行同步操作的性能提高了很多,节省了加锁的开销。

     

    先用最普通的方法在线程中访问对象读取数据。

    private void queryThread() {
            final Query query = sonDao.queryBuilder().build();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    List<Son> sonList =  query.list();
                    Log.d("son",sonList.get(0).getName());
                }
            }).start();
        }

    运行程序会抛出一个异常。

    信息提示方法使用应该仅在当前线程,使用forCurrentThread()方法为这个线程获得一个事例。(该方法返回一个查询类Query)

    现在添加这个方法。

     private void queryThread() {
            final Query query = sonDao.queryBuilder().build();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //forCurrentThread()该方法返回一个Query对象
                    List<Son> sonList =  query.forCurrentThread().list();
                    Log.d("son",sonList.get(0).getName());
                }
            }).start();
        }

    运行成功。

     

    接下来了解下如何多线程查询的,以及了解这个方法。

    还记得上一篇讲到的四个查询方法吗?因为查询方法中都有线程检查的方法。

     protected void checkThread() {
            if (Thread.currentThread() != ownerThread) {
                throw new DaoException(
                        "Method may be called only in owner thread, use forCurrentThread to get an instance for this thread");
            }
        }

    很熟悉,异常就是这个方法抛出的。下面来看查询正确的过程是怎样实现多线程查询的。

    点进去方法forCurrentThread(),以下就是多线程查询的核心代码

    /**
         * Just an optimized version, which performs faster if the current thread is already the query's owner thread.
         * Note: all parameters are reset to their initial values specified in {@link QueryBuilder}.
         */
        Q forCurrentThread(Q query) {
            if (Thread.currentThread() == query.ownerThread) {
                System.arraycopy(initialValues, 0, query.parameters, 0, initialValues.length);
                return query;
            } else {
                return forCurrentThread();
            }
        }
    
        /**
         * Note: all parameters are reset to their initial values specified in {@link QueryBuilder}.
         */
        Q forCurrentThread() {
            // Process.myTid() seems to have issues on some devices (see Github #376) and Robolectric (#171):
            // We use currentThread().getId() instead (unfortunately return a long, can not use SparseArray).
            // PS.: thread ID may be reused, which should be fine because old thread will be gone anyway.
            long threadId = Thread.currentThread().getId();
            synchronized (queriesForThreads) {
                WeakReference<Q> queryRef = queriesForThreads.get(threadId);
                Q query = queryRef != null ? queryRef.get() : null;
                if (query == null) {
                    gc();
                    query = createQuery();
                    queriesForThreads.put(threadId, new WeakReference<Q>(query));
                } else {
                    System.arraycopy(initialValues, 0, query.parameters, 0, initialValues.length);
                }
                return query;
            }
        }

    意思就是:只是一个优化版本,如果当前线程已经是查询的所有者线程,则执行速度更快。

    注意:所有参数都重置为{@link QueryBuilder}中指定的初始值

     

    讲解一下。

    先判断线程是否是当前线程,如果是的话,就copy query的信息到一个数组中,并且返回一个query。其实这个方法就是源码里面说的当前线程的话执行速度更快,指的就是这个,因为if包含的这段代码是判断为主线程成立运行的。

    否则的话(当前线程不是主线程)就调用下面的forCurrentThread()方法。

    注释说:Process.myTid()在一些设备上有为题;我们使用了currentThread().getId()代替了旧版本,返回一个long;线程ID可以重复使用,这应该没问题,因为旧线程无论如何都会消失。

    (我写下这段的时候也有点懵逼-----。。。。。)

    方法先记录线程ID,然后加线程锁,锁的是一个final Map<Long, WeakReference<Q>> queriesForThreads;然后通过get()方法得到一个对象并判断赋值给query,接着判断query,然后经过gc()方法,最后返回一个query给用户。(待我更强之后回来续写这段--------)

     

    所以,forCurrentThread()方法返回一个query类给用户,然后我们就可以进行查询了。

     

    展开全文
  • springboot项目-多线程查询示例

    千次阅读 2019-09-09 23:41:18
    对于多线程,使用到项目的场景并不是多,但是多线程查询算是一个。 以多线程查询人员列表为例: pom.xml文件:maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=...

    对于多线程,使用到项目的场景并不是多,但是多线程查询算是一个。

    以多线程查询人员列表为例:

    1. pom.xml文件:maven依赖
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
      
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>1.5.9.RELEASE</version>
              <relativePath/>
          </parent>
      
          <groupId>com.demo.thread</groupId>
          <artifactId>springmuiltThread</artifactId>
          <version>1.0-SNAPSHOT</version>
      
          <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
              <java.version>1.8</java.version>
          </properties>
      
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-jdbc</artifactId>
              </dependency>
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
                  <scope>runtime</scope>
              </dependency>
              <dependency>
                  <groupId>org.mybatis.spring.boot</groupId>
                  <artifactId>mybatis-spring-boot-starter</artifactId>
                  <version>1.3.2</version>
              </dependency>
              <dependency>
                  <groupId>com.google.guava</groupId>
                  <artifactId>guava</artifactId>
                  <version>17.0</version>
              </dependency>
       
              <dependency>
                  <groupId>cn.hutool</groupId>
                  <artifactId>hutool-all</artifactId>
                  <version>4.6.3</version>
              </dependency>
          </dependencies>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-maven-plugin</artifactId>
                  </plugin>
              </plugins>
          </build>
      
      </project>

       

    2. controller
      package com.zengqingfa.thread.controller;
      
      /*
       *  @ author  zengqingfa
       *  @ created in    2019/9/9  20:05
       *
       */
      
      import com.zengqingfa.thread.entity.Emp;
      import com.zengqingfa.thread.service.EmpService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestMethod;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      
      import java.util.List;
      
      @RestController
      @RequestMapping("/emp/")
      public class EmpController {
      
          @Autowired
          private EmpService empService;
      
          @RequestMapping(value = "findAll", method = RequestMethod.GET)
          List<Emp> findAll() {
              List<Emp> empList = empService.findAll();
              return empList;
          }
      
          @RequestMapping(value = "findAll2", method = RequestMethod.GET)
          List<Emp> findAll2() {
              List<Emp> empList = empService.findAll2();
              return empList;
          }
      
          @RequestMapping(value = "findByPage", method = RequestMethod.GET)
          List<Emp> findByPage(@RequestParam Integer pageNo, @RequestParam Integer pageSize) {
              List<Emp> empList = empService.findByPage(pageNo, pageSize);
              return empList;
          }
      
          @RequestMapping(value = "findById", method = RequestMethod.GET)
          Emp findById(@RequestParam Integer id) {
              Emp emp = empService.findById(id);
              return emp;
          }
      }
      

       

    3. service
      接口
      ```
      package com.zengqingfa.thread.service;
      
      /*
       *  @ author  zengqingfa
       *  @ created in    2019/9/9  20:05
       *
       */
      
      import com.zengqingfa.thread.entity.Emp;
      
      import java.util.List;
      
      public interface EmpService {
      
          List<Emp> findAll();
      
      
          List<Emp> findAll2();
      
          Emp findById(Integer id);
      
          Integer findCount();
      
      
          List<Emp> findByPage(Integer pageNo, Integer pageSize);
      }
      
      
      
      
      ```
      实现类:
      ```
      package com.zengqingfa.thread.service.impl;
      
      /*
       *  @ author  zengqingfa
       *  @ created in    2019/9/9  20:15
       *
       */
      
      import cn.hutool.core.collection.CollUtil;
      import com.zengqingfa.thread.dao.EmpDao;
      import com.zengqingfa.thread.entity.Emp;
      import com.zengqingfa.thread.service.EmpService;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      
      @Service
      public class EmpServiceImpl implements EmpService {
      
          private static final Logger LOGGER = LoggerFactory.getLogger(EmpServiceImpl.class);
      
          @Autowired
          private EmpDao empDao;
      
          @Override
          public List<Emp> findAll() {
              LOGGER.error("start....");
              long start = System.currentTimeMillis();
              Integer count = empDao.findCount();
              List<Emp> list = empDao.findAll();
              LOGGER.error("查询全部消耗了:" + (System.currentTimeMillis() - start) + "s");
              LOGGER.error("end....");
              return list;
          }
      
          @Override
          public List<Emp> findAll2() {
              LOGGER.error("start....");
              long start = System.currentTimeMillis();
              List<Emp> empListVos = new ArrayList<>();
              try {
                  Integer total = empDao.findCount();
                  int threadSize = total / 10;//每页大小
                  int threadNum = total % threadSize == 0 ? total / threadSize : total / threadSize + 1;//总页数
                  ExecutorService exec = Executors.newFixedThreadPool(threadNum);  //threadNum线程数
                  List<Callable<Integer>> tasks = new ArrayList<>();
                  Callable<Integer> task = null;
                  Map<Integer, List<Emp>> map = new HashMap();
                  for (int i = 1; i <= threadNum; i++) {
                      final int pageNum = i;
                      task = new Callable<Integer>() {
                          @Override
                          public Integer call() throws Exception {
                              List<Emp> partyOrgPersonVoList = findByPage(pageNum, threadSize);
                              map.put(pageNum, partyOrgPersonVoList);
                              return 1;
                          }
                      };
                      tasks.add(task);
                  }
                  exec.invokeAll(tasks);
                  if (CollUtil.isNotEmpty(map)) {
                      for (int i = 1; i <= threadNum; i++) {
                          List<Emp> empVos = map.get(i);
                          empListVos.addAll(empVos);
                          map.remove(i);
                      }
                  }
                  exec.shutdown();
                  LOGGER.error("【批量查询人员信息】线程任务执行结束,执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
              } catch (Exception e) {
                  LOGGER.error(e.getMessage());
              }
              return empListVos;
          }
      
      
          @Override
          public Emp findById(Integer id) {
              return empDao.findById(id);
          }
      
          @Override
          public Integer findCount() {
              return empDao.findCount();
          }
      
          @Override
          public List<Emp> findByPage(Integer pageNo, Integer pageSize) {
              Integer offset = (pageNo - 1) * pageSize;
              return empDao.findByPage(offset, pageSize);
          }
      }
      
      
      
      
      ```
      
      
      
      
      
      
      
      
      
      
      

       

    4. dao
      dao接口
      
      package com.zengqingfa.thread.dao;
      
      /*
       *  @ author  zengqingfa
       *  @ created in    2019/9/9  20:14
       *
       */
      
      import com.zengqingfa.thread.entity.Emp;
      import org.apache.ibatis.annotations.Mapper;
      import org.apache.ibatis.annotations.Param;
      
      import java.util.List;
      
      @Mapper
      public interface EmpDao {
      
          List<Emp> findAll();
      
          Emp findById(Integer id);
      
          Integer findCount();
      
          List<Emp> findByPage(@Param("offset") Integer offset, @Param("pageSize") Integer pageSize);
      }
      

       

    5. 实体类:Emp
      package com.zengqingfa.thread.entity;
      
      /*
       *  @ author  zengqingfa
       *  @ created in    2019/9/9  20:10
       *
       */
      
      import java.util.Date;
      
      public class Emp {
      
          private Integer id;
          private Integer empno;
          private String ename;
          private String job;
          private Integer mgr;
          private Date hiredate;
          private Double sal;
          private Double comm;
          private Integer deptno;
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public Integer getEmpno() {
              return empno;
          }
      
          public void setEmpno(Integer empno) {
              this.empno = empno;
          }
      
          public String getEname() {
              return ename;
          }
      
          public void setEname(String ename) {
              this.ename = ename;
          }
      
          public String getJob() {
              return job;
          }
      
          public void setJob(String job) {
              this.job = job;
          }
      
          public Integer getMgr() {
              return mgr;
          }
      
          public void setMgr(Integer mgr) {
              this.mgr = mgr;
          }
      
          public Date getHiredate() {
              return hiredate;
          }
      
          public void setHiredate(Date hiredate) {
              this.hiredate = hiredate;
          }
      
          public Double getSal() {
              return sal;
          }
      
          public void setSal(Double sal) {
              this.sal = sal;
          }
      
          public Double getComm() {
              return comm;
          }
      
          public void setComm(Double comm) {
              this.comm = comm;
          }
      
          public Integer getDeptno() {
              return deptno;
          }
      
          public void setDeptno(Integer deptno) {
              this.deptno = deptno;
          }
      }
      

       

    6. 配置文件:application.xml,当有多个配置文件时,如测试,开发等时使用
      spring:
          profiles:
            active: dev

       

    7. 配置文件:application-dev.xml
      server:
        port: 8080
      
      spring:
        datasource:
          username: root
          password: root
          url: jdbc:mysql://localhost:3306/bigdata?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
          driver-class-name: com.mysql.jdbc.Driver
      
      mybatis:
        mapper-locations: classpath:mapping/*Mapper.xml
        type-aliases-package: com.zengqingfa.thread.entity

       

    8. 线程池参数配置文件:spring.xml
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
      
          <bean id="queryPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
              <!-- corePoolSize  -->
              <property name="corePoolSize" value="2"/>
              <!-- 线程池维护线程的最大数量 -->
              <property name="maxPoolSize" value="4"/>
              <!-- 线程池所使用的缓冲队列 -->
              <property name="queueCapacity" value="1000"/>
              <!--线程池维护线程所允许的空闲时间 -->
              <property name="keepAliveSeconds" value="3000"/>
              <!-- 核心线程在空闲keepAliveSeconds后也timeout -->
              <property name="allowCoreThreadTimeOut" value="true"/>
              <!--线程名称 -->
              <property name="threadNamePrefix" value="ExecutorService-thread-"/>
          </bean>
      
      
      
      
      
      </beans>

       

    9. 配置类:ConfigClass
      package com.zengqingfa.thread.config;
      
      import org.mybatis.spring.annotation.MapperScan;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.ImportResource;
      
      
      @Configuration
      @ImportResource(locations = {"classpath:spring.xml"})
      @MapperScan(value = "com.zengqingfa.thread.dao")
      public class ConfigClass {
      }
      

       

    10. 映射文件:EmpMapper.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.zengqingfa.thread.dao.EmpDao">
      
          <resultMap id="EmpResultMap" type="com.zengqingfa.thread.entity.Emp">
              <result column="id" jdbcType="INTEGER" property="id"/>
              <result column="empno" jdbcType="INTEGER" property="empno"/>
              <result column="ename" jdbcType="VARCHAR" property="ename"/>
              <result column="job" jdbcType="VARCHAR" property="job"/>
              <result column="mgr" jdbcType="INTEGER" property="mgr"/>
              <result column="hiredate" jdbcType="DATE" property="hiredate"/>
              <result column="sal" jdbcType="NUMERIC" property="sal"/>
              <result column="comm" jdbcType="NUMERIC" property="comm"/>
              <result column="deptno" jdbcType="INTEGER" property="deptno"/>
          </resultMap>
      
          <select id="findById" parameterType="java.lang.Integer" resultMap="EmpResultMap">
              select * from emp where id = #{id}
          </select>
      
          <select id="findAll" resultMap="EmpResultMap">
              select * from emp
          </select>
      
          <select id="findCount" resultType="java.lang.Integer">
              select COUNT(*) from emp
          </select>
      
          <select id="findByPage2" resultMap="EmpResultMap" parameterType="java.lang.Integer">
              select * from emp
              LIMIT #{offset},#{pageSize};
          </select>
      
      
          <select id="findByPage" resultMap="EmpResultMap" parameterType="java.lang.Integer">
             SELECT * FROM emp  WHERE id>=
             (SELECT id FROM emp LIMIT #{offset},1)  LIMIT #{pageSize};
          </select>
      
      
      </mapper>
      

       

    11. 测试结果:http://localhost:8080/emp/findAll   ;    http://localhost:8080/emp/findAll2
      2019-09-10 00:16:06.626 ERROR 41024 --- [nio-8080-exec-1] c.z.thread.service.impl.EmpServiceImpl   : start....
      2019-09-10 00:16:08.379 ERROR 41024 --- [nio-8080-exec-1] c.z.thread.service.impl.EmpServiceImpl   : 多线程查询:线程任务执行结束,执行任务消耗了 :1752毫秒
      2019-09-10 00:16:11.014 ERROR 41024 --- [nio-8080-exec-4] c.z.thread.service.impl.EmpServiceImpl   : start....
      2019-09-10 00:16:14.024 ERROR 41024 --- [nio-8080-exec-4] c.z.thread.service.impl.EmpServiceImpl   : 单线程查询:线程任务执行结束,执行任务消耗了 :3010毫秒
      2019-09-10 00:16:14.024 ERROR 41024 --- [nio-8080-exec-4] c.z.thread.service.impl.EmpServiceImpl   : end....

      本次查询是以50万条数据记录进行演示的效果:发现,多线程查询速度还是有提升的,提升还是比较明显的。实际的线程数根据实际情况进行调整。但是我试了开启10个线程,15个 线程 ,20个线程,对比之下,提升并不明显。

    12. 附录mysql创建50万条sql语句脚本:

      -- 创建数据库
      create database test_thread;
      use test_thread;
       
       
      #1 建表dept
      CREATE TABLE dept(  
      id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,  
      deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,   
      dname VARCHAR(20) NOT NULL DEFAULT "",  
      loc VARCHAR(13) NOT NULL DEFAULT ""  
      ) ENGINE=INNODB DEFAULT CHARSET=GBK ;
      
      
      #2 建表emp
      CREATE TABLE emp  
      (  
      id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,  
      empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/  
      ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/  
      job VARCHAR(9) NOT NULL DEFAULT "",/*工作*/  
      mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/  
      hiredate DATE NOT NULL,/*入职时间*/  
      sal DECIMAL(7,2) NOT NULL,/*薪水*/  
      comm DECIMAL(7,2) NOT NULL,/*红利*/  
      deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/  
      )ENGINE=INNODB DEFAULT CHARSET=GBK ;
      
      
      show variables like 'log_bin_trust_function_creators'; 
      set global log_bin_trust_function_creators=1;
      
      
      -- 产生随机字符串
      
      DELIMITER $$
      CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
      BEGIN
       DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
       DECLARE return_str VARCHAR(255) DEFAULT '';
       DECLARE i INT DEFAULT 0;
       WHILE i < n DO
       SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
       SET i = i + 1;
       END WHILE;
       RETURN return_str;
      END $$
      
      #用于随机产生部门编号
      DELIMITER $$
      CREATE FUNCTION rand_num( ) 
      RETURNS INT(5)  
      BEGIN   
       DECLARE i INT DEFAULT 0;  
       SET i = FLOOR(100+RAND()*10);  
      RETURN i;  
       END $$
       
       
      #假如要删除
      #drop function rand_num;
      
      #执行存储过程,往dept表添加随机数据
      DELIMITER $$
      CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))  
      BEGIN  
      DECLARE i INT DEFAULT 0;   
       SET autocommit = 0;    
       REPEAT  
       SET i = i + 1;  
       INSERT INTO dept (deptno ,dname,loc ) VALUES ((START+i) ,rand_string(10),rand_string(8));  
       UNTIL i = max_num  
       END REPEAT;  
       COMMIT;  
       END $$
      
      
      
      DELIMITER $$
      CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))  
      BEGIN  
      DECLARE i INT DEFAULT 0;   
      #set autocommit =0 把autocommit设置成0  
       SET autocommit = 0;    
       REPEAT  
       SET i = i + 1;  
       INSERT INTO emp (empno, ename ,job ,mgr ,hiredate ,sal ,comm ,deptno ) VALUES ((START+i) ,rand_string(6),'SALESMAN',0001,CURDATE(),2000,400,rand_num());  
       UNTIL i = max_num  
       END REPEAT;  
       COMMIT;  
       END $$
       
      #删除
      # DELIMITER ;
      # drop PROCEDURE insert_emp;
      
      
      DELIMITER ;
      #执行存储过程,往dept中插入10条数据
      CALL insert_dept(100,10); 
       
       select count(1) from dept;
       
      #执行存储过程,往emp表添加50万条数据
      DELIMITER ;
      CALL insert_emp(100001,500000); 
      select count(*) from emp;
      
      
      select * from emp;

       

    展开全文
  • 利用php开发语言开发curl多线程查询百度收录情况
  • java使用多线程查询大批量数据

    万次阅读 热门讨论 2019-12-11 18:18:22
    前言 在某些时候,一旦单表数据量过大,查询数据的时候就会变得...这个查询的过程,数据量一旦过大,单线程查询数据将会成为瓶颈,下面尝试使用多线程来尝试查询一张数据量较大的表 由于代码逻辑不是很难,直接上...
  • 多线程查询数据

    千次阅读 2016-08-16 17:14:49
    多线程查询数据: 此处主要是对内存与数据的联系的理解,如使用到的地二级指针 #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #define N 2027358 char **g_bh; void init...
  • java多线程查询

    千次阅读 2015-05-22 12:37:50
    下面是多线程查询的部分代码,提供给大家参考下: 线程类: 带返回值的类要实现Callable接口,具体业务逻辑没有实现,只是写了个空方法在里面 package com.sanfy.demo.thread; import java.util.List; import java....
  • java多线程查询数据库

    2017-12-04 13:38:37
    java多线程并发查询数据库,使用线程池控制分页,并发查询
  • 使用多线程查询大量数据信息

    千次阅读 2019-08-16 09:47:10
    使用多线程查询大量数据信息 1、创建一个线程池: public class ThreadPoolExecutorFactory { public static final ExecutorService executor = Executors.newFixedThreadPool(20); } 2、创建一个...
  • python使用多线程查询数据库

    万次阅读 2019-02-01 17:04:39
     当数据量过大时,一个程序的执行时间就会主要花费在等待单次查询返回结果,在这个过程中cpu无疑是处于等待io的空闲状态的,这样既浪费了cpu资源,又花费了大量时间(当然这里主要说多线程,批量查询不在考虑范围,...
  • mybatis多线程查询数据库

    千次阅读 2019-04-21 17:10:09
    查询费用汇总和明细时使用1条sql查询在数据库阻塞锁表,所以拆成4条小sql,先按分页和查询条件查询出满足的customerCd再通过customerCd多线程4次异步调用查询数据和未结算金额及结算金额和总条数 在查询group by和...
  • oracle数据库,我设置多线程(1-10)访问数据库的几张表A\B\C(表中均有大概500W数据,索引已做好),1-3访问AB,4-10访问BC,单独执行这些查询基本都在4-6秒左右,但是多线程之后有的线程去查询表需要30多秒。...
  • Java多线程查询多表操作

    千次阅读 2019-08-27 10:58:11
    Java实现多线程的方式有几种: 1.继承Thread类,重写run()方法,通过start()方法运行run()方法; 2.实现Runnable接口,同样是重写run()方法; 3.实现Callable接口通过FutureTask包装器来创建Thread线程; 4....
  • mysql多线程查询处理.

    千次阅读 2018-01-09 16:32:14
    mysql多线程问题 mysql多线程处理不好,经常会发生coredump 单线程 一般情况下,单线程连接mysql代码如下: /* single_thread_mysql_client.cpp */ #include #include #include #...
  • 多线程查询数据库

    千次阅读 2008-12-08 02:09:00
    所以打算用多线程来实现,可是当在线程里面执行到 this.dataGridDF.DataSource=dt.DefaultView;填充数据时却提示报错,说什么该线程不能调用主线程创建的控件等等。后来查了许多资料,终于搞定。可以在查询数据库时...
  • 最近在公司碰到这么一个需求,需要去1000多个数据库中统计数据,每次统计数据库中10多张表,当我们同事写出代码后,由于单线程去执行,效率有点慢,所以想出用多线程进行查询,这样以来可以提升一下查询效率。...
  • spring mybatis的多线程查询功能

    千次阅读 2018-01-25 19:47:14
    最近几天写我的自己的项目的时候用到数据的实例化,这个...所以我想起用多线程的方式去同时查询数据返回。 * 类名称:ThreadPoolUtil * 类描述:线程池查询 * 创建人:fulln * 创建时间:2018年1月25日 下午7:1
  • 千万级数据多线程查询

    千次阅读 2019-01-04 21:04:53
    public class AnalysisSalseTask implements Callable<AnalysisSalesVo> { private TbAnalysisSalesMapper baseMapper;...//分段查询开始时间 private String endTIme;//分段查询结束时间 private...
  • //就是下面这句多线程查询执行时间越往后越慢 o = odsDB.executeBatchQuery(tableName, MAX_BATCH_NUM*m, MAX_BATCH_NUM); if(o != null) { toDB.executeBatchInsert(insertSQL, o); toDB.commit(); } } }...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 462,560
精华内容 185,024
关键字:

多线程查询