某些情况下,你的需求列表中的某一个子任务所花费的时间可能是你不能控制,不能预知的(譬如url获取请求数据)。有的时候它很快,有的时侯得到结构需要花费你预料以外的很长时间,最终阻塞了你的主线程,使得你的主线程快慢依赖于这个看起来并不那么重要的功能。也许你需要给这个子任务限定一个时间段,在这个时间段内得不到数据后你的主线程转身离开,不过遗憾的是这个子任务的处理的api没有提供某一时间得不到结构就向你报告的行为。
如果你碰到这种情况,FurtureTask可以作为一个备选的解决方案:
FurtureTask是一个java.lang.Runnable接口的实现子类和java.util.concurrent.Future接口的实现子类。所以它可以作为Thread的传入参数后被start(),同时Future接口行为提供get(long timeout, TimeUnit unit)的API,当在指定的时间内得不到结果后就抛出定制的TimeoutException异常。关于FurtureTask更详细的行为请参考javadoc和周钦的多线程案例,下面给出使用的案例,本案例侧重get(timeout, unit)的使用(TimeUnit 一个enum类):
/**
* 为url访问并获取返回字符串独立开启一个线程
* 为了达到可控时间内获取返回值(如果超过一定时间没有返回结果,将不再等待返回结果,避免主线程过长时间阻塞)
* 结合FutureTask使用
* @author Administrator
*
*/
public class UrlCallor implements Callable {
public UrlCallor(String url ){
this.url = url;
}
private String url ;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public Object call() throws Exception {
String _ating_data ;
// System.out.println(url);
Parser parser = new Parser(url);
parser.setEncoding("utf-8");
NodeIterator ni = parser.elements();
if(ni!=null){
_ating_data = ni.nextNode().toPlainTextString().trim();
//System.out.println(ni.nextNode().toPlainTextString());
}else{
_ating_data = "";
}
return _ating_data;
}
}
public class AiTingUtil {
private static Logger log = Logger.getLogger(AiTingUtil.class);
public static String getAtingDts(String name){
String _ating_data ="{}";
String url = null;
try {
url = "****";
} catch (UnsupportedEncodingException e) {
log.error("aiting url error:"+e);
return "";
}
// System.out.println(url);
log.info(" URL:"+url);
UrlCallor urlcallor = new UrlCallor(url);
FutureTask<String> _ft = new FutureTask<String>(urlcallor);
Thread _urlthread = new Thread(_ft);
_urlthread.start();
try {
_ating_data = _ft.get(200, TimeUnit.MILLISECONDS);
}catch(Exception ex){
log.error("等待数据200毫秒以上,异常信息:"+ex);
_ating_data ="";
}
return _ating_data;
}
public static void main(String[] args){
System.out.println(new AiTingUtil().getAtingDts("郭德纲"));
}
}