Android 线程池及多线程下载,Progressbar动态更新以及文件保存sd卡

来源:互联网 发布:淘宝购物车不小心删除 编辑:程序博客网 时间:2024/04/30 05:21

最近研究了android 多线程下载的用法,写了一个小demo,总结一下学习知识和分享一下学习经验吧。
线程池代码为:ThreadPool.java

public final class ThreadPool {    // 线程池中默认线程的个数为5    private static int worker_num = 5;    // 工作线程    private WorkThread[] workThreads;    // 任务队列,作为一个缓冲,List线程不安全    private List<Runnable> taskQueue = new LinkedList<Runnable>();    private static ThreadPool threadPool;    // 创建具有默认线程个数的线程池    private ThreadPool() {        this(5);    }    // 创建线程池,worker_num为线程池中工作线程的个数    private ThreadPool(int worker_num) {        ThreadPool.worker_num = worker_num;        workThreads = new WorkThread[worker_num];        for (int i = 0; i < worker_num; i++) {            workThreads[i] = new WorkThread();            workThreads[i].start();// 开启线程池中的线程        }    }    // 单态模式,获得一个默认线程个数的线程池    public static ThreadPool getThreadPool() {        return getThreadPool(ThreadPool.worker_num);    }    // 单态模式,获得一个指定线程个数的线程池,worker_num(>0)为线程池中工作线程的个数    // worker_num<=0创建默认的工作线程个数    public static ThreadPool getThreadPool(int worker_num1) {        if (threadPool == null)            threadPool = new ThreadPool(worker_num1);        return threadPool;    }    // 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器觉定    public void addTask(Runnable task) {        synchronized (taskQueue) {            taskQueue.add(task);            taskQueue.notifyAll();        }    }    // 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁    public void destroy() {        while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧            try {                Thread.sleep(10);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        // 工作线程停止工作,且置为null        for (int i = 0; i < worker_num; i++) {            workThreads[i].stopWorker();            workThreads[i] = null;        }        threadPool = null;        taskQueue.clear();// 清空任务队列    }    /**     * 内部类,工作线程     */    private class WorkThread extends Thread {        // 该工作线程是否有效,用于结束该工作线程        private boolean isRunning = true;        /*         * 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待         */        @Override        public void run() {            Runnable r = null;            while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了                synchronized (taskQueue) {                    while (isRunning && taskQueue.isEmpty()) {// 队列为空                        try {                            taskQueue.wait(20);                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                    if (!taskQueue.isEmpty())                        r = taskQueue.remove(0);// 取出任务                }                if (r != null) {                    r.run();// 执行任务                }                r = null;            }        }        // 停止工作,让该线程自然执行完run方法,自然结束        public void stopWorker() {            isRunning = false;        }    }}

此内容为引用别人写的代码,拿来主义时代就是这样!
好了,现在来看下下载文件的代码吧:

public class PoolRunnable implements Runnable{    private static final String TAG = "PoolRunnable";    private static final String FILE_PATH = "/Sid/download/";    private String urlString;    private int flag; //针对多个任务下载时,区别不同的任务    private File savePath;    private DownLoadBackListener listener;    public PoolRunnable(String url, int flag) {        urlString = url;        this.flag = flag;    }    public void setDownLoadListener(DownLoadBackListener ls) {        listener = ls;    }    @Override    public void run() {        // TODO Auto-generated method stub        HttpClient client = new DefaultHttpClient();        HttpGet get = new HttpGet(urlString);        try {            HttpResponse response = client.execute(get);            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {                InputStream is = response.getEntity().getContent();                long length = response.getEntity().getContentLength();                boolean isOk = getSavePath(length);                if(!isOk) {                    listener.downFaile("Not enough storage space", flag);                    return;                }                Log.i(TAG, "flag:"+flag+"savePath:"+savePath);                OutputStream os = new FileOutputStream(savePath);                byte[] buffer = new byte[1024];                int count = 0;                long total = 0;                while((count = is.read(buffer)) != -1) {                    os.write(buffer, 0, count);                    total += count;                    listener.downLoadProgress((int)(total*100/length), flag);                }                is.close();                os.close();                listener.downLoadOver(savePath.getAbsolutePath(), flag);            } else listener.downFaile(""+response.getStatusLine().getStatusCode(), flag);        } catch (ClientProtocolException e) {            // TODO Auto-generated catch block            e.printStackTrace();            listener.downFaile(e.getMessage(), flag);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();            listener.downFaile(e.getMessage(), flag);        }    }    /**     * 检测是否有sd卡,以及是否有足够的存储空间     * @param length     * @return     */    public synchronized boolean getSavePath(long length) {        String basePath;        String name = urlString.substring(urlString.lastIndexOf("/"));        if(Environment.getExternalStorageState().endsWith(Environment.MEDIA_MOUNTED) &&                isAvailableSpac(Environment.getExternalStorageDirectory().getAbsolutePath(), length)) {            basePath = Environment.getExternalStorageDirectory().getAbsolutePath();            savePath = checkSavePath(basePath, name);        } else if(isAvailableSpac(Environment.getRootDirectory().getAbsolutePath(), length)){            basePath = Environment.getRootDirectory().getAbsolutePath();            savePath = checkSavePath(basePath, name);        } else return false;        File baseFile = new File(basePath + FILE_PATH);        baseFile.mkdirs();        try {            savePath.createNewFile();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return true;    }    /**     * 当有多个同样的文件存在时,按序号存储     */    public synchronized File checkSavePath(String base, String name) {        savePath = new File(base + FILE_PATH + name);        if(savePath.exists()) {            name = name.substring(0, name.indexOf("."));            Log.i(TAG, "name:"+name);            for (int i = 1; i < Integer.MAX_VALUE; i++) {                String last = name +"("+i+").apk";                savePath = new File(base + FILE_PATH + last);                if(!savePath.exists()) break;            }        }        return savePath;    }    /**     * 判断是否有足够的存储空间     * @param path 文件保存地址     * @param size 要保存的文件大小     * @return     */    @SuppressWarnings("deprecation")    public boolean isAvailableSpac(String path, long size) {        StatFs statFs = new StatFs(path);        long blockSize = statFs.getBlockSize();        long blocks = statFs.getAvailableBlocks();        long availableSpare = blocks * blockSize;        Log.i("TAG", "剩余空间availableSpare = " + availableSpare);        if (availableSpare > size) {            return true;        }        return false;    }    /**     * 下载结果回馈接口     * @author user     *     */    public interface DownLoadBackListener {        //下载进行的时候,返回进度        public void downLoadProgress(int progress, int flag);         //下载完成时调用        public void downLoadOver(String success, int flag);        //下载失败时调用        public void downFaile(String faile, int flag);    }}

好了,干实事的就是以上这些代码了,下面看一下怎么调用他们吧:

ThreadPool pool = ThreadPool.getThreadPool(3);        barOne = (ProgressBar) findViewById(R.id.pool_progressBar1);        barTwo = (ProgressBar) findViewById(R.id.pool_progressBar2);        barThree = (ProgressBar) findViewById(R.id.pool_progressBar3);        barFour = (ProgressBar) findViewById(R.id.pool_progressBar4);        barFive = (ProgressBar) findViewById(R.id.pool_progressBar5);        PoolRunnable oneRun = new PoolRunnable(DOWNLOAD_PATH, 1);        PoolRunnable twoRun = new PoolRunnable(DOWNLOAD_PATH, 2);        PoolRunnable threeRun = new PoolRunnable(DOWNLOAD_PATH, 3);        PoolRunnable fourRun = new PoolRunnable(DOWNLOAD_PATH, 4);        PoolRunnable fiveRun = new PoolRunnable(DOWNLOAD_PATH, 5);        oneRun.setDownLoadListener(this);        twoRun.setDownLoadListener(this);        threeRun.setDownLoadListener(this);        fourRun.setDownLoadListener(this);        fiveRun.setDownLoadListener(this);        pool.addTask(oneRun);        pool.addTask(twoRun);        pool.addTask(threeRun);        pool.addTask(fourRun);        pool.addTask(fiveRun);

下载回调接口的实现:

@Override    public void downLoadProgress(int progress, int flag) {        // TODO Auto-generated method stub        switch (flag) {        case 1:            barOne.setProgress(progress);            break;        case 2:            barTwo.setProgress(progress);            break;        case 3:            barThree.setProgress(progress);            break;        case 4:            barFour.setProgress(progress);            break;        case 5:            barFive.setProgress(progress);            break;        default:            break;        }    }    @Override    public void downLoadOver(String success, int flag) {        // TODO Auto-generated method stub        Log.i(TAG, "flag:"+flag+";success:"+success);    }    @Override    public void downFaile(String faile, int flag) {        // TODO Auto-generated method stub        Log.i(TAG, "flag:"+flag+";success:"+faile);    }

具体方法的代码,还是要看自己想要处理的事情了。

好了就这么多了,有需要的下载demo看一下效果吧 ^~^

1 0
原创粉丝点击