Java多線程Future的使用


先直接上代碼如下:

一、需要實現Callable接口(可以使用泛型)

package com.innotek.spms.service.finance;

import com.innotek.common.util.SpringContextUtil;
import com.innotek.spms.entity.busi.Collector;
import com.innotek.spms.entity.busi.Payment;
import com.innotek.spms.entity.fanc.PaymentCard;
import com.innotek.spms.entity.swap.OwefeeRecord;
import com.innotek.spms.entity.swap.RepayRecord;
import com.innotek.spms.entity.tran.PayOrder;
import com.innotek.spms.service.PayBackService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.Callable;

public class RepayTask implements Callable<Long> {

private PayOrder payOrder;
private Collector collector;
private Payment payment;
private String payAccount;
private String cityCode;
private OwefeeRecord owefeeRecord;
private RepayRecord tempEntity;
private long oweFee;
private long paymentId;
private PaymentCard card;

public RepayTask(PayOrder payOrder, Collector collector, Payment payment,
String payAccount, String cityCode, OwefeeRecord owefeeRecord, RepayRecord tempEntity,
long oweFee, long paymentId, PaymentCard card) {

this.payOrder=payOrder;
this.collector=collector;
this.payment=payment;
this.payAccount=payAccount;
this.cityCode=cityCode;
this.owefeeRecord=owefeeRecord;
this.tempEntity=tempEntity;
this.oweFee=oweFee;
this.paymentId=paymentId;
this.card=card;
}


@Override
public Long call() throws Exception {
PayBackService payBackService=(PayBackService) SpringContextUtil.getBean("payBackService");

return payBackService.eliminateRecordImpl(payOrder, collector, payment,
payAccount, cityCode, owefeeRecord, tempEntity, oweFee,
paymentId, card);


}
}

二、創建線程池使用:

// 線程執行補繳接口
ExecutorService executor= Executors.newCachedThreadPool();
List<RepayTask> taskList=new ArrayList<RepayTask>();
RepayTask task=new RepayTask(payOrder, collector, payment,
payAccount, cityCode, owefeeRecord, tempEntity, oweFee,
paymentIdFianl, card);
taskList.add(task);
List<Future<Long>>resultList=null;
try {
//執行全部的線程
resultList=executor.invokeAll(taskList);
if(CollectionUtils.isNotEmpty(resultList)){
for (int i=0; i<resultList.size(); i++){
Future<Long> future=resultList.get(i);
sum+= future.get();
}
}
} catch (Exception e) {
e.printStackTrace();
}

三、其他詳解如下:

並發編程時,一般使用runnable,然后扔給線程池完事,這種情況下不需要線程的結果。 
所以run的返回值是void類型。 

如果是一個多線程協作程序,比如菲波拉切數列,1,1,2,3,5,8...使用多線程來計算。 
但后者需要前者的結果,就需要用callable接口了。 
callable用法和runnable一樣,只不過調用的是call方法,該方法有一個泛型返回值類型,你可以任意指定。 

線程是屬於異步計算模型,所以你不可能直接從別的線程中得到函數返回值。 
 這時候,Future就出場了。Futrue可以監視目標線程調用call的情況,當你調用Future的get()方法以獲得結果時,當前線程就開始阻塞,直接call方法結束返回結果。 

下面三段簡單的代碼可以很簡明的揭示這個意思: 
 
runnable接口實現的沒有返回值的並發編程。 
 
callable實現的存在返回值的並發編程。(call的返回值String受泛型的影響) 
 
同樣是callable,使用Future獲取返回值。

package demo.future;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
* 試驗 Java 的 Future 用法
*/

public class FutureTest {

public static class Task implements Callable<String> {
@Override
public String call() throws Exception {
String tid = String.valueOf(Thread.currentThread().getId());
System.out.printf("Thread#%s : in call\n", tid);
return tid;
}
}

public static void main(String[] args) throws InterruptedException, ExecutionException {
List<Future<String>> results = new ArrayList<Future<String>>();
ExecutorService es = Executors.newCachedThreadPool();
for(int i=0; i<100;i++)
results.add(es.submit(new Task()));

for(Future<String> res : results)
System.out.println(res.get());
}

}


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com