简单组装线程池

后天就是大年初一啦!提前祝大家2017年大吉大利!

步入正题
其实我们从网络上拉取(加载)一张图片很简单,随随便便几行代码搞定,那我们的图片拉取池的意义在什么地方呢?首先我们用于图片拉取的线程是可控的,也就是说可以随时取消。其次我们内部封装了一层线程池,保证了我们拉取的图片是有序的。对于如何得到拉取之后的图片,我采用的是接口回调,每拉取一次都会返回给调用者。

好,现在我们看代码。

public class ThreadPool {
    
    private static ExecutorService exec;
    private static ThreadPool threadPool;
    
    public static ThreadPool getInstance(){
        if(threadPool != null){
            return threadPool;
        }
        synchronized (ThreadPool.class) {
            if(threadPool == null){
                threadPool = new ThreadPool();
            }
        }
        return threadPool;
    }
    
    private ThreadPool(){
        exec = Executors.newFixedThreadPool(1);
    }
    
    public ThreadListener exec(Runnable runnable){
        Future<?> future = exec.submit(runnable);
        ThreadListener listener = new ThreadListener(future);
        return listener;
    }
    
    public static class ThreadListener{
        
        private Future<?> f;
        
        public ThreadListener(Future<?> future){
            this.f = future;
        }
        
        //试图取消线程,返回true表示取消成功
        public boolean cancle(){
            return f.cancel(true);
        }
        
        //判断是否完成
        public boolean isDone(){
            return f.isDone();
        }
    }
    
}

这里使用单例模式对线程池进行了一层封装,注意这里我们并没有使用execute()方法,而是采用submit方法并返回一个Future对象,这样做的好处就是,我们可以控制线程,可以随时取消并且判断是否完成等等。

public interface Callback {

    void getBitmap(Bitmap bitmap);

}

接口,用于返回bitmap。

public class LoadImage {

    private ThreadPool.ThreadListener threadListener;
    private String url;
    private final int readTimeout = 8*1000;
    private final int connectTimeout = 8*1000;
    private final String requestMethod = "GET";
    private InputStream inputStream;
    private Callback callback;

    public LoadImage(String url, Callback callback){
        this.callback = callback;
        ThreadPool threadPool = ThreadPool.getInstance();
        this.url = url;
        threadListener = threadPool.exec(new Runnable() {
            @Override
            public void run() {
                runnableWorker();
            }
        });
    }

    private void runnableWorker(){
        try {
            URL mURL = new URL(url);
            HttpURLConnection httpURLConnection = (HttpURLConnection) mURL.openConnection();
            httpURLConnection.setRequestMethod(requestMethod);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            httpURLConnection.setReadTimeout(readTimeout);
            httpURLConnection.setConnectTimeout(connectTimeout);
            inputStream = httpURLConnection.getInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            callback.getBitmap(bitmap);
        } catch (IOException e) {
            callback.getBitmap(null);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean cancle(){
        return threadListener.cancle();
    }

    public boolean isDone(){
        return threadListener.isDone();
    }
}

这里我们对接口、线程池以及网络拉取进行二次封装。现在核心的方法我们已经封装完毕,针对于不同的使用,我们可以再进行一层简单的封装调用。

使用就非常简单了:

new LoadImage("图片网址", new Callback() {
            @Override
            public void getBitmap(Bitmap bitmap) {

            }
        });

笔者能力有限,不足之处欢迎指出!

    原文作者:麦兜叮叮当
    原文地址: https://www.jianshu.com/p/92dc8170c04c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞