当我们面临大量数据查询的时候,在我有限的技术生涯中,想到两种解决方案。
1.建立专业的solr查询引擎,实现全文检索。
2.多线程加速查询的过程。
后台管理系统,数据量不算大,但是来源较多。较杂。
目前的处理方式是用多线程实现。
那么,问题来了,多线程的查询,关键问题在于,传递了参数,如何将查询出的结果返回。
解决方案是采用Callable:
一、一个简单的demo
package com.test.test;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
public class CallableThread implements Callable<Map<String,Integer>> {
//传递进来的参数
int data;
private Map <String,Integer> map =new HashMap <String,Integer>();//定义需要返回的map
private final CountDownLatch latch ;
public CallableThread( int data, CountDownLatch latch) {
this.data = data;
this.latch = latch;
}
public Map<String,Integer> call() throws Exception {
try{
//每个参数手动增加100
data+=100;
map.put("data", data);
System.out.println("线程:"+Thread.currentThread().getName());
}catch(Exception e){
e.printStackTrace();
}finally{
latch.countDown();
}
return map;
}
}
package com.test.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(5);
ExecutorService pool=Executors.newFixedThreadPool(5);
List list=new ArrayList();
try {
for(int j=0;j<5;j++){
Callable<Map<String, Integer>> c1 = new CallableThread(j,latch);
Future<Map<String,Integer>> f1=pool.submit(c1);
list.add(f1);
}
latch.await();
for(int i=0;i<list.size();i++){
Future<Map<String,Integer>> f1=(Future<Map<String, Integer>>) list.get(i);
System.out.println((Integer)f1.get().get("data"));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
输出结果:
上述例子,将0-4的值传递进入多线程,返回的数据是加了100的。证明Callable接口是可以实现数据的返回注意
用法简要说明:
1.多线程类CallableThread实现Callable<Map<String,Integer>> 接口。在该类的成员变量中,定义chua传递进来的参数。Callable后接着的泛型Map<String,Integer>代表你需要返回的数据的类型。
2.CountDownLatch用于记录正在执行的线程数量,5个线程,那就创建五个CountDownLatch。并且在多线程环境内,执行完毕了业务逻辑之后,要调用latch.countDown()方法,代表这个线程执行完毕了,正在执行的线程数减一。
3.多线程内部是没有异常处理机制的。所以,我们一定要记得手动加上try,catch,finally。并且在finally里面执行latch.countDown();方法,确保线程发生异常的情况下,也可以顺利地将正在执行的线程数减一。否则,如果latch.countDown();得不到执行,你将看不到异常,看不到报错,程序就一直停留在多线程的执行中。
4.当所有线程执行完毕之后,在测试方法中执行latch.await();方法,然后批量拿取值即可。返回带有泛型的Future类。