Android 线程池模拟多线程并发下载任务

废话不多,直接上源码

自定义一个Adapter

public class MyAdapter extends BaseAdapter {
    private Context context;
    private List<Progress> list;
    private Object lockobj = new Object();//对象锁

    private int complteTask = 0;//当前完成下载任务的数量

    private DownloadCompleteCall mCallback;//所有下载任务完成的回调方法

    public interface DownloadCompleteCall {
        void downloadComplete();
    }

    public MyAdapter(Context context, List<Progress> list, DownloadCompleteCall mCallback) {
        this.context = context;
        this.list = list;
        this.mCallback = mCallback;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.progress_layout, null);
            viewHolder = new ViewHolder();
            viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress);
            viewHolder.textView = (TextView) convertView.findViewById(R.id.progress_text);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        Progress curProgress = (Progress) getItem(position);
        viewHolder.textView.setText("任务" + position + ":" + curProgress.getProgress() + "%");
        viewHolder.progressBar.setProgress(curProgress.getProgress());
        return convertView;
    }

    public void update(int proBarIndex, int result) {
        if (proBarIndex < 0 || proBarIndex >= list.size()) {
            return;
        }
        Progress curPro = list.get(proBarIndex);
        curPro.setProgress(result);
        if (result == 100) {
            complteTask++;
        }
        if (complteTask == list.size()) {
            mCallback.downloadComplete();//如果完成的任务数等于总数,说明下载完成,回调
        }
        notifyDataSetChanged();
    }

    //获取任务列表中第一个没有在运行的任务
    public int getProBarIndex() {
        synchronized (lockobj) {
            for (int i = 0; i < list.size(); i++) {
                if (!list.get(i).isRunning()) {
                    list.get(i).setRunning(true);
                    return i;
                }
            }
        }
        return -1;
    }

    class ViewHolder {
        TextView textView;
        ProgressBar progressBar;
    }
}

帮助类:

public class Progress {
    private int index;
    private int progress;
    private boolean running;

    public Progress(int index, int progress, boolean running) {
        this.index = index;
        this.progress = progress;
        this.running = running;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }

    public boolean isRunning() {
        return running;
    }

    public void setRunning(boolean running) {
        this.running = running;
    }
}


主界面:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="模拟同时下载线程数:"/>

        <EditText
            android:hint="默认3个"
            android:id="@+id/countEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="应用"/>

    <ListView
        android:id="@+id/listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

    </ListView>
</LinearLayout>

MainActivity代码

public class MainActivity extends Activity implements MyAdapter.DownloadCompleteCall {
    private final static int DEFAULT_DOWNLOAD_CONTHREAD = 3;//默认并发线程为3
    private final static int DEFAULT_DOWNLOAD_SUM = 20;//下载任务总数

    private final static int ACTION_UPDATE_PROGRESS = 0;
    private final static int ACTION_START_DOWNLOAD = 1;

    @Bind(R.id.countEditText)
    EditText countEditText;
    @Bind(R.id.listview)
    ListView listview;

    private MyAdapter myAdapter;
    private int conThread;
    private boolean hasRunning = false;

    ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "DownloadTask#" + mCount.getAndIncrement());//线程的名称
        }
    };
    BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);//队列最多接收128个任务的缓存
    private ExecutorService threadPool;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == ACTION_START_DOWNLOAD) {
                startDownload(conThread);//开始模拟下载
            } else if (msg.what == ACTION_UPDATE_PROGRESS) {
                myAdapter.update(msg.arg1, msg.arg2);//更新adapter
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initListView();
    }

    private void initListView() {
        List<Progress> progresses = new ArrayList<Progress>();
        for (int i = 0; i < DEFAULT_DOWNLOAD_SUM; i++) {
            Progress progress = new Progress(i, 0, false);
            progresses.add(progress);
        }
        myAdapter = new MyAdapter(this, progresses, this);
        listview.setAdapter(myAdapter);
    }

    @OnClick(R.id.start)
    void setThread() {
        if (hasRunning) {
            return;
        }
        conThread = DEFAULT_DOWNLOAD_CONTHREAD;
        try {
            conThread = Integer.parseInt(countEditText.getText().toString());
            if (conThread > DEFAULT_DOWNLOAD_SUM) {
                conThread = DEFAULT_DOWNLOAD_SUM;
            } else if (conThread < 0) {
                conThread = DEFAULT_DOWNLOAD_CONTHREAD;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        hasRunning = true;
        handler.sendEmptyMessage(ACTION_START_DOWNLOAD);

    }

    private void startDownload(int conThread) {
        if (threadPool != null) {
            threadPool.shutdown();
            threadPool = null;
        }
        //此时conThread个线程并发,如果还有任务进来,就放入sPoolWorkQueue队列中等待运行
        threadPool = new ThreadPoolExecutor(conThread, conThread, 0, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);

        for (int i = 0; i < DEFAULT_DOWNLOAD_SUM; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    int result = 0;
                    int proBarIndex = myAdapter.getProBarIndex();
                    while (true) {
                        try {
                            //result等于100的时候,结束该下载任务
                            if (result == 100) {
                                break;
                            }
                            int sleepTime = (int) (Math.random() * 1000);
                            Thread.sleep(sleepTime);
                            result += 10;
                            Message msg = new Message();
                            msg.what = ACTION_UPDATE_PROGRESS;
                            msg.arg1 = proBarIndex;
                            msg.arg2 = result;
                            handler.sendMessage(msg);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        }

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            //shutDownThreadPool();如果想要back键退出应用,仍后台下载,注释该行
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void downloadComplete() {
        shutDownThreadPool();//下载完成之后,关闭线程池,可以看到所有下载任务完成之后,并行的线程DownloadTask#1到3,就结束了
    }

    private void shutDownThreadPool(){
        if (threadPool != null) {
            threadPool.shutdown();
        }
    }
}


实际运行效果:  此时设置了并行下载线程为10个。。。

分析:见代码注释

更多线程池的知识  Android AsyncTask原理以及线程池概念

源码下载:BinJing/PoolSimulateDownloadTask

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值