java future 性能,多线程之Future和Callable【高性能应用场景java.util.concurrent】

业务场景:

如查一个数据集合,第一页至第一百页,返回总页数的总结集,然后导出。

一次需要limit 0 10000,这样,一个SQL查询出非常慢。

但用100个线程,一个线程只查limit0 10 就非常快了,

利用多线程的特性,返回多个集合,在顺序合并成总集合。

下面是concurrent.Future  例子

concurrent.Callable

package com.test.thread;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

/**

*  Future>

*

*  应用场景 :1.多线程,每个线程平均任务耗时一样

*          2.需要顺序返回的

*

*  顺序返回,如多个分页,但第一页需要先返回

*

* @author 汪兴安

*

*/

public class ThreadTest {

/**

* 定义线程池

*/

public static ExecutorService executos = Executors.newFixedThreadPool(5);

public static void main(String[] args) {

/**

* 定义集合装结果集

*/

ListtotalList = new ArrayList();

/**

* 定义 Future泛型的集合对象,装多线程的,返回信息

*/

List>> list = new ArrayList>>();

try {

int pageIndex = 0;

int maxPage = 6;

for (pageIndex = 0; pageIndex < maxPage; pageIndex++) {

/**

* executos.submit 返回线程未来结果

*/

Future> future = executos.submit(new DemoThread(pageIndex));

list.add(future);

}

for (Future> dataFuture : list) {

获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行

totalList.addAll(dataFuture.get());  //dataFuture.get()  这里会阻塞   有顺序的哦

}

//得到分页后结果总共集合

for (int i = 0; i < totalList.size(); i++) {

System.out.println(totalList.get(i).getName());

}

} catch (Exception e) {

e.printStackTrace();

}

executos.shutdownNow();

}

/**

*  查询第1页

查询第3页

查询第5页

查询第2页

查询第4页

查询第0页

-----结果会顺序返回,不用你操心顺序问题啦

anan0

anan1

anan2

anan3

anan4

anan5

*/

}

package com.test.thread;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Callable;

/**

* Callable 支持有返回值的多线程

* @author 汪兴安

*

*/

public class DemoThread implements Callable> {

private int pageIndex;

/**

* 通过构造器,初始化

* @param pageIndex

*/

public DemoThread(int pageIndex) {

this.pageIndex = pageIndex;

}

@Override

public Listcall() throws Exception {

//模拟每个线程执行耗时不一样

if(pageIndex%2==0)

{

Thread.sleep(5000);

}else

{

Thread.sleep(2000);

}

System.out.println("查询第" + pageIndex + "页");

Listlist = new ArrayList();

/**

* 模拟查询的数据对象

*/

User user=new User();

user.setAge(""+pageIndex);

user.setName("anan"+pageIndex);

list.add(user);

return list;

}

}

===================================华丽分割线=================================================================================

package com.test.thread;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Executors;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.CompletionService;

import java.util.concurrent.ExecutorCompletionService;

import java.util.concurrent.ExecutionException;

/**

*

* @author 汪兴安

* 应用场景 :1.每个线程耗时差别大,谁先完成,谁返回

* 对顺序没有要求。

*

*

*

* CompletionService 的性能更高。

* 考虑如下场景:多线程下载,结果用Future返回。

* 第一个文件特别大,后面的文件很小。

* 用方法1,能很快知道已经下载完文件的结果(不是第一个);

*

*/

public class CallableAndFuture {

public static void main(String[] args) {

ListtotalList = new ArrayList();

ExecutorService threadPool = Executors.newCachedThreadPool();

CompletionService> cs = new ExecutorCompletionService>(threadPool);

for(int i = 0; i < 6; i++) {

cs.submit(new DemoThread(i));

}

// 可能做一些事情

for(int i = 0; i < 6; i++) {

try {

totalList.addAll(cs.take().get());

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

}

//得到分页后结果总共集合

for (int i = 0; i < totalList.size(); i++) {

System.out.println(totalList.get(i).getName());

}

}

/**

* 查询第3页

查询第1页

查询第5页

查询第2页

查询第0页

查询第4页

anan5

anan1

anan3

anan2

anan0

anan4

*/

}

总结:两种方式,应用场景不一样

Future> future = executos.submit(new DemoThread(pageIndex));   这种可以保证返回的顺序

CompletionService> cs = new ExecutorCompletionService>(threadPool);,返回不保证顺序,谁先执行完,谁先返回。

效率上CompletionService更高,实际项目需要根据具体业务需求选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值