callable与runable相结合

本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。

       Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值,

public class Taskwithcallable implements Callable<String>{
    private int id;
    
    public Taskwithcallable(int id){
        this.id=id;
    }
    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        
        return "result of Taskwithcallable"+id;
        
    }
    public static void main(String[] args){
        ExecutorService exec =Executors.newCachedThreadPool();
        ArrayList<Future<String>> result=new ArrayList<Future<String>>();
        //将线程池执行Taskwithcallable,返回值为调用的call方法,返回类型为Future,将结果放在ArrayList中
        for(int i=0;i<=5;i++)result.add(exec.submit(new Taskwithcallable(i)));
        for(Future<String> fs:result){
            try {
                System.out.println(fs.get());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                exec.shutdown();
            }
        }
    }

}result of Taskwithcallable0
result of Taskwithcallable1
result of Taskwithcallable2
result of Taskwithcallable3
result of Taskwithcallable4
result of Taskwithcallable5


 

说说Runnable与Callable

Callable接口:

public interface Callable<V> {
    V call() throws Exception;
}

 

Runnable接口:

public interface Runnable {
    public abstract void run();
}

 

相同点:

  1. 两者都是接口;(废话)
  2. 两者都可用来编写多线程程序;
  3. 两者都需要调用Thread.start()启动线程;

 

不同点:

  1. 两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
  2. Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

项目例子:

1:定义多线程类:实现Callable接口;

重写call方法:call方法的返回值是CircDoDetailDataOrgResult ,然后CircDoDetailDataOrgResult 的实现类中有RetCode,Errbuf两个属性,分别是作为执行多线程的call方法的返回结果和返回值!

public class CircCreateXmlCallable implements Callable<CircDoDetailDataOrgResult> {
private CircContext context;
private String filePath;
private CircRepOrgs repOrg;
private CircRepDataOrgs repDataOrg;
private CircIndexSets indexSet;
private CircPeriod period;
private ICircReportXmlAttachmentService xmlService;
private MessageSource messageSource;
public CircCreateXmlCallable(CircContext context, String filePath, CircRepOrgs repOrg, CircRepDataOrgs repDataOrg, CircIndexSets indexSet, CircPeriod period,
ICircReportXmlAttachmentService xmlService, MessageSource messageSource) {
this.context = context;
this.filePath = filePath;
this.repOrg = repOrg;
this.repDataOrg = repDataOrg;
this.indexSet = indexSet;
this.period = period;
this.xmlService = xmlService;
this.messageSource = messageSource;
}
@Override
public CircDoDetailDataOrgResult call() {
String retCode, errbuf;
CircDoDetailDataOrgResult result = new CircDoDetailDataOrgResult();
retCode = "0";
errbuf = " Completed Successfully.";
try {
this.xmlService.createXmlPerDistrictCodeByDOM(context, filePath, repOrg, repDataOrg, indexSet, period);
result.setRetCode(retCode);
result.setErrbuf(errbuf);
String msg = "District code:[" + repDataOrg.getDistrictCode() + "] xml file has been created sucessfully.";
CircLogUtil.info(msg);
} catch (Exception e) {
retCode = "2";
errbuf = "Completed With Error." + messageSource.getMessage(e.getMessage(), null, CircConstant.CIRC_DEFAULT_LOCALE) + ";" + MsgUtil.msg(e);
result.setRetCode(retCode);
result.setErrbuf(errbuf);
}
return result;
}

}

2:调用线程类,执行线程方法;

①首先使用ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount);创建线程池;

②接下来List<CircCreateXmlCallable> callables = new ArrayList<CircCreateXmlCallable>(); list中的CircCreateXmlCallable就是步骤1中定义的线程类,这个list用来装线程类;

  :然后生成线程类的实例myCallable ;将myCallable加入到list中去,callables.add(myCallable);

  :List<Future<CircDoDetailDataOrgResult>> futureList = executor.invokeAll(callables);线程池executor启动,执行

     线程中的call方法,然后用Future接口将线程执行返回的结果接收到,future.get()得到结果!

@Service
@Transactional(rollbackFor = Exception.class)
public class CircReportXmlAttachmentServiceImpl extends BaseServiceImpl<CircReportXmlAttachment> implements ICircReportXmlAttachmentService {

@Autowired
private CircIndexSetsMapper indexSetsMapper;
@Autowired
private CircRepOrgsMapper repOrgsMapper;
@Autowired
private ICircContextService contextService;
@Autowired
private CircRepDataOrgsMapper repDataOrgsMapper;
@Autowired
private CircPeriodMapper periodMapper;
@Autowired
private ICircIndexResultsService indexResultsService;
@Autowired
private MessageSource messageSource;
public void threadCreateXml(CircContext context, String filePath, CircRepOrgs repOrg, List<CircRepDataOrgs> repDataOrgsList, CircIndexSets indexSet, CircPeriod period)
throws InterruptedException, ExecutionException, HdmpException, SQLException {
int threadCount = CircConstant.DEFAULT_CREATEXML_THREAD_COUNTS;
// 多线程循环处理
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount);
String msg = "Successfully fetched thread [" + threadCount + "].";
CircLogUtil.info(msg);

try {
List<CircCreateXmlCallable> callables = new ArrayList<CircCreateXmlCallable>();
for (CircRepDataOrgs repDataOrg : repDataOrgsList) {
CircCreateXmlCallable myCallable = new CircCreateXmlCallable(context, filePath, repOrg, repDataOrg, indexSet, period, this, messageSource);
callables.add(myCallable);
}

List<Future<CircDoDetailDataOrgResult>> futureList = executor.invokeAll(callables);

String districtCode, retCode, errbuf;
boolean existsErrorFlag = false;
for (Future<CircDoDetailDataOrgResult> future : futureList) {
retCode = future.get().getRetCode();
errbuf = future.get().getErrbuf();


if (!CircConstant.RETCODE_SUCESSFULL.equals(retCode)) {
existsErrorFlag = true;
districtCode = future.get().getDistrictCode();
msg = "District code:[" + districtCode + "].Fail to complete.The message is [" + errbuf + "]";
CircLogUtil.error(msg);
}
}


if (existsErrorFlag) {
throw new HdmpException("circ.threadcompletewitherror.exception");
}
} finally {
executor.shutdown();
}


}

 

例子2:

list<Future<map<String,Object>>> result接收返回的结果,结果为map<String,Object>类型的map集合;

返回结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值