在andorid里面,线程间的切换非常频繁.任何耗时的操作就会导致,这种rxjava就很顺势的出来了,结构简单,切换简单,随用随走.那么如果不会rxjava.似乎有handler通知方法,或者说runonuithread..多个线程之间的通知怎么办呢.这种时候.在java中就有一个类Future的使用就产生了.=-=老大说,不能用第三方,只能用原生.并且不能有跳出线程的地方.
举个栗子:这个栗子是抄的
假如你突然想做饭,但是没有厨具,也没有食材。网上购买厨具比较方便,食材去超市买更放心。
实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材。所以,在主线程里面另起一个子线程去网购厨具。
但是,子线程执行的结果是要返回厨具的,而run方法是没有返回值的。所以,这才是难点,需要好好考虑一下。
这里我对Future进行了封装,让其更好的使用.而且跟线程进行结合使用
XFuture<T> mFutureResult = new XFuture<>();
这次我使用的是下载文件的请求.此时已经在子线程中.将请求到数据设置到Result中.通过setResult方法
File file = new File(mContext.getCacheDir(), MD5.md5(downUrl) + ".png");
if (file.exists()) {
// 防止多次下载
mFutureResult.setResult(file);
return;
}
GetTask是请求的子线程,数据还是在其中请求,但是,外部已经开始获取Result.这种时候,getLoad方法仍然要在子线程中.因为我在内部做了阻塞的操作
GetTask getTask = new GetTask(mContext, IconUrl);
getNativeTask.execute(ThreadManager.getNetExecutor());
File imageFile = GetTask.getLoad();
这样就能获取到数据
贴上部分下载代码
public GetTask(Context context, String url) {
super("getImage");
this.mContext = context;
this.downUrl = url;
}
public File getLoad()
throws CodeException {
// 设置超时事件
File file = this.mFutureResult.get(30000L, TimeUnit.MILLISECONDS);
if (null != file) {
return file;
}
throw new IOException(-4, "load timeout");
}
@Override
protected void doFire() {
File file = new File(mContext.getCacheDir(), MD5.md5(downUrl) + ".png");
if (file.exists()) {
// 防止多次下载
mFutureResult.setResult(file);
return;
}
byte[] bytes = WebUtils.doGet(downUrl);
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(bytes, 0, bytes.length);
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mFutureResult.setResult(file);
}
这样操作就好了.没有通过任何第三方,完成自己的多线程操作.亲测可用
贴上封装代码.
public class XFuture<R>
implements Future<R> {
private static final String TAG = "XFuture";
private boolean done = false;
private boolean cancelled = false;
private String message = null;
private R result = null;
public boolean isDone() {
return this.done;
}
public boolean isCancelled() {
return this.cancelled;
}
public R get() {
if (!this.done) {
ensureNotOnMainThread();
}
synchronized (this) {
if (!this.done) {
try {
wait();
} catch (InterruptedException e) {
LOG.e("XFuture", "wait result failed(InterruptedException)", e);
setMessage(e.getMessage());
}
}
}
return (R) this.result;
}
public R get(long timeout, TimeUnit unit) {
if (!this.done) {
ensureNotOnMainThread();
}
synchronized (this) {
if (!this.done) {
try {
long millis = unit.toMillis(timeout);
long start = System.currentTimeMillis();
wait(millis);
long interval = System.currentTimeMillis() - start;
if ((interval >= millis) &&
(!this.done)) {
LOG.e("XFuture", "[" + timeout + " " + unit + "] wait result timeout(" + interval + "MS)");
setMessage("timeout");
}
} catch (InterruptedException e) {
LOG.e("XFuture", "[" + timeout + " " + unit + "] wait result failed(InterruptedException)", e);
setMessage(e.getMessage());
}
}
}
return (R) this.result;
}
public boolean cancel(boolean interrupt) {
this.cancelled = true;
this.message = "cancelled";
this.result = null;
synchronized (this) {
notifyAll();
this.done = true;
}
return true;
}
public void setResult(R result) {
this.cancelled = false;
this.result = result;
synchronized (this) {
notifyAll();
this.done = true;
}
}
public String toString() {
return "QFuture{d=" + this.done + " c=" + this.cancelled + " m=" + this.message + " r=" + this.result + "}";
}
protected void setMessage(String message) {
this.message = message;
}
private void ensureNotOnMainThread() {
Looper myLooper = Looper.myLooper();
Looper mainLooper = Looper.getMainLooper();
if ((null != myLooper) && (myLooper == mainLooper)) {
IllegalStateException e = new IllegalStateException("calling on main thread may lead to deadlock and/or ANRs");
throw e;
}
}
}