遇到数返回慢,从程序角度分析优化。
1、底层数据查询优化(sql)优化,减少内存运算操作。
2、增加缓存,减少数据查询(如:使用redis)。
3、分析业务流水,将串行处理的工作并行处理。
本文主要介绍串行任务并行化处理。
并发
前提:一个主任务依赖于不同的子任务结果,而各子任务之间相互隔离(不相关)。这样,可以考虑将子任务并行处理。这就会用到线程相关知识,然后就就是线程池等。
思路演变过程:
1、对不同的子任务启动线程来处理(通过实现Runnable处理)。
问题1:如何从线程中获取返回值?
思路:构造函数设值(传入的对象要和线程的私有变量指向同一堆内存)。
问题2:如何实现分步结束后,主任务才能执行。
思路:使用CountDownLatch计数器实现线程等待。
2、使用Callable返回结果,通过Future的get方法获取线程返回结果。
其中,Future的get方法是阻塞式的,这样,主线程就会一直等待,知道所有子线程的返回。
最终,也是选择了此乃方法。
3、线程池管理
线程的生命周期管理,交给线程池处理。这里使用 java.util.concurrent.ExecutorService处理,线程池使用newCachedThreadPool线程池。
延申四种缺省线程池:
1.newCachedThreadPool() | -缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中 -缓存型池子通常用于执行一些生存期很短的异步型任务 因此在一些面向连接的daemon型SERVER中用得不多。 -能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。 注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。 |
2. newFixedThreadPool | -newFixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程 -其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子 -和cacheThreadPool不同,FixedThreadPool没有IDLE机制(可能也有,但既然文档没提,肯定非常长,类似依赖上层的TCP或UDP IDLE机制之类的),所以FixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器 -从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同: fixed池线程数固定,并且是0秒IDLE(无IDLE) cache池线程数支持0-Integer.MAX_VALUE(显然完全没考虑主机的资源承受能力),60秒IDLE |
3.ScheduledThreadPool | -调度型线程池 -这个池子里的线程可以按schedule依次delay执行,或周期执行 |
4.SingleThreadExecutor | -单例线程,任意时间池中只能有一个线程 -用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE) |
示例代码:
辅助类:工人实体
package com.zhq.threadpool;
/**
* 工人
* @author alanzhang211
*
*/
public class Worker {
private Integer age;
private String name;
public Integer getAge() {
return age;
}
public Worker(){};
public Worker(String name,Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString(){
return this.getName() + “年龄:” + this.getAge();
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1、Thread实现:
1.1 Thread工作线程
package com.zhq.threadpool;
import java.util.concurrent.CountDownLatch;
/**
* Thread实现
* @author alanzhang211
*
* @param <T>
*/
public class MyThread<T> implements Runnable{
/**
* 计数器
*/
private CountDownLatch latch;
/**
* 操作算子
*/
private String opType;
/**
* 需要返回的数据
*/
private T data;
/**
* 索引
*/
private Integer index;
public MyThread(CountDownLatch latch,String opType,T data,Integer indexParam) {
this.latch = latch;
this.opType = opType;
this.data = data;
this.index = indexParam;
}
@SuppressWarnings(“unchecked”)
@Override
public void run() {
if (opType != null && opType.equals(“Worker”)) {
try {
Thread.sleep(3000);//模拟线程工作
Worker tempWorker = new Worker(“工作后:”,(index+1));
data = (T) tempWorker;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(data+”工作线程:”+Thread.currentThread().getName());
}
latch.countDown();
}
}
2、Callable实现
package com.zhq.threadpool;
import java.util.concurrent.Callable;
/**
*
* @author alanzhang211
*
* @param <V>
*/
public class MyCallable<V> implements Callable<V> {
private V data;
public MyCallable(V data) {
super();
this.data = data;
}
@Override
public V call() throws Exception {
Thread.sleep(3000);
System.out.println(data+”工作线程:”+Thread.currentThread().getName());
return data;
}
}
3、测试类
package com.zhq.threadpool;
import java.util.ArrayList;
import java.util.List;
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;
/**
*
* @author alanzhang211
*
*/
public class ThreadPoolExecutorTest {
/**
* Thread实现
*/
public void threadMethod(){
ExecutorService executorService = Executors.newCachedThreadPool();
int workerNum = 5;
CountDownLatch latch = new CountDownLatch(workerNum);//工作线程
MyThread<?> worker = null;
Object data = null;
for (int i = 0; i < workerNum; i++) {
data = new Worker();
((Worker) data).setAge(i);
((Worker) data).setName(“工人”+i);
System.out.println(“工作前:”+data.toString());
worker = new MyThread<Worker>(latch, “Worker”, (Worker)data,i);
executorService.execute(worker);
System.out.println(“worker返回:”+worker.toString());
try {
Thread.sleep(1000);//模拟主线程业务处理1s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“=====”+worker.toString()+”结束工作”);
}
}
/**
* callable实现
*/
public void callableMethod(){
ExecutorService executorService = Executors.newCachedThreadPool();
Worker worker = null;
List<Future<?>> resultList = new ArrayList<Future<?>>();
for (int i = 0; i < 5; i++) {
worker = new Worker();
worker.setAge(i);
worker.setName(“工人”+i);
Future<Worker> future = executorService.submit(new MyCallable<Worker>(worker));
resultList.add(future);
System.out.println(“=====”+worker.toString()+”开始工作”);
try {
//get()方法阻塞式,阻塞main 主线程
// System.out.println(future.get());
Thread.sleep(1000);//模拟主线程业务处理1s
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“=====”+worker.toString()+”结束工作”);
}
Future<Integer> futureInt = executorService.submit(new MyCallable<Integer>(0));
resultList.add(futureInt);
//增加Integer包装类
Future<Integer> futureInteger = executorService.submit(new MyCallable<Integer>(new Integer(1)));
resultList.add(futureInteger);
try {
for (Future<?> futuretemp : resultList) {
System.out.println(“get获取线程返回的结果:”+futuretemp.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
ThreadPoolExecutorTest test = new ThreadPoolExecutorTest();
test.callableMethod();
// test.threadMethod();
System.out.println(“耗时:”+(System.currentTimeMillis() – startTime ) + “ms”);
}
}