java多线程实战 线程池
多线程创建方式
java创建多线程的方法常用的有三种:
1、继承Thread类,重写 run方法。start是开启线程
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread.run()");
}
}
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
2、实现Runnable接口,如果一个类有继承的其他类就可以通过实现Runnable接口来创建多线程。
public class MyThread implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start(); //开启线程
3、获得有返回值的线程,需要实现Callable方法并且重写call方法
public class MyCallable<V> implements Callable<V> {
@Override
public V call() throws Exception {
// TODO Auto-generated method stub
return null;
}
}
Callable<V> callable = new MyCallable<V>();
//由Callable<Integer>创建一个FutureTask<Integer>对象:
FutureTask<V> task = new FutureTask<V>(callable);
//FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。
//由FutureTask<Integer>创建一个Thread对象:
Thread Thread = new Thread(task);
Thread.start(); //开启线程
线程池多线程实战
业务逻辑:我们需要查询数据库中的主机性能数据根据不同的主机进行查询出来在前台进行绘制图表,每次页面显示10个图表即10个主机的数据(可变),每次查询查询一个主机的数据sql所用的时间是0.07s差不多,十个是0.7s再加上数据处理渲染下来整个页面加载出来的时间大概在2s左右,比较缓慢,之后在优化的过程 中考虑了一下多线程去处理获取这个数据,最后算下来加载时间能到1s左右。
思路:采用newFixedThreadPool线程池去创建多线程,并且去实现callable接口,来接受线程的返回值。使用callable和future获取返回的结果
线程类:核心处理数据的方法在call方法里。
//执行任务的线程 有返回值的 查询服务
class ServiceTask implements Callable<Map<String,ImageTableServiceBean>>{
int start;
int end;
String startTime;
String endTime;
String hostname;
String servicename;
ImageTableMapper imageTableMapper;
public ServiceTask(int start,int end,String startTime,String endTime,String hostname,String servicename
,ImageTableMapper imageTableMapper){
this.start=start;
this.end=end;
this.startTime=startTime;
this.endTime=endTime;
this.hostname=hostname;
this.servicename=servicename;
this.imageTableMapper=imageTableMapper;
}
@Override
public Map<String,ImageTableServiceBean> call() throws Exception {
List<ImageTableServiceBean> its=imageTableMapper.getNewImageTableService(start,end,startTime,endTime,hostname,servicename);
ImageTableServiceBean isb=DataUtils.getImageTableServiceData(its);
Map<String,ImageTableServiceBean> map=new HashMap<String,ImageTableServiceBean>();
map.put(hostname+":"+servicename, isb);
System.err.println("service线程 == "+Thread.currentThread().getName()+"== 正在运行");
return map;
}
}
执行类:通过线程池去 执行线程 将线程添加到futureTask里 可以获取到返回结果
ExecutorService threadPool = Executors.newFixedThreadPool(4);//固定大小的线程池;
//进行异步任务列表--服务
List<FutureTask<Map<String,ImageTableServiceBean>>> futureTasks = new ArrayList<FutureTask<Map<String,ImageTableServiceBean>>>();
for(ImageTableServiceName ser:servicesName){
//创建线程
ServiceTask t1=new ServiceTask(start,end,startTime,endTime,ser.getHostname(),ser.getServicename(), imageTableMapper);
//加入到 future任务队列
FutureTask<Map<String,ImageTableServiceBean>>task=new FutureTask<Map<String,ImageTableServiceBean>>(t1);
futureTasks.add(task);//添加到集合
threadPool.submit(task);//执行线程 future
}
//通过循环遍历线程 可获取到线程返回 的结果
for(FutureTask<Map<String,ImageTableServiceBean>> futureTask:futureTasks){
try {
Map<String,ImageTableServiceBean> isb = futureTask.get();//获取线程返回的结果 会阻塞直到返回结果
itsMap.putAll(isb);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}