Android-工作遭遇-打造多线程响应式编程基础架子(Future)

在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;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/ci250454344/article/details/82871662
今日推荐