线程池的使用(三)

一.概述

今天我们继续研究线程池的使用,因为这块确实可能比较麻烦,不多研究几次是根本不能搞懂的,先看效果图

效果一

这里写图片描述

效果二

这里写图片描述

二.代码

效果一(纯ExecutorService、AsyncTask、Runnable关联实现相关文件如下)

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    //任务编号
    private static int order = 0;
    /**
     * 总共多少任务(根据CPU个数决定创建活动线程的个数,这样取的好处就是可以让手机承受得住)
     */
//    private static final int count = Runtime.getRuntime().availableProcessors()*2;
    private static final int count = 6;//任务总数
    /**
     * 每次只执行一个任务的线程池
     */
    private static ExecutorService sSingleThreadExecutor;
    /**
     * 没有任务个数限制的线程池
     */
    private static ExecutorService sCachedThreadPool;
    /**
     * 限制任务个数的线程池
     */
    private static ExecutorService sFixedThreadPool;
    /**
     * 按指定时间可周期性执行任务的线程池
     */
    private static ExecutorService sScheduledThreadPool;
    /**
     * 按指定时间可周期性执行任务的线程池,按照指定的工厂模式
     */
    private static ExecutorService sScheduledThreadPool1;
    private List<PoolTask> mPoolTasks;
    private ListView mListView;
    private boolean isCancel = false;
    private boolean isClick = false;
    /**
     * 当前线程执行器类型
     */
    private static ExecutorService currentExecutor ;
    /**
     * 方式一,使用默认线程工厂
     */
    ThreadFactory ft = Executors.defaultThreadFactory();
    /**
     * 方式二,创建新线程需要的线程工厂
     */
    private static ThreadFactory mThreadFactory = new ThreadFactory() {
        private final AtomicInteger count = new AtomicInteger();
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, "threadPool" + count.getAndIncrement());
            thread.setDaemon(true);
            return thread;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.listview);
        mListView.setOnItemClickListener(mOnItemClickListener);
        initData();
    }
    public void initData(){
        sSingleThreadExecutor = Executors.newSingleThreadExecutor();
        sCachedThreadPool = Executors.newCachedThreadPool();
        sFixedThreadPool = Executors.newFixedThreadPool(3);
        sScheduledThreadPool = Executors.newScheduledThreadPool(3);
        sScheduledThreadPool1 = Executors.newScheduledThreadPool(4, mThreadFactory);
        sSingleThreadExecutor.submit(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "run: task is sumbit");
            }
        });
        currentExecutor = sSingleThreadExecutor;
        mListView.setAdapter(new ThreadPoolAdapter(this, count));
    }

    AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (position == 0) {
                //第一种关闭方式,等待正在执行的任务执行完成
//                    sCachedThreadPool.shutdown();
                    /*
                    shutdownNow:停止正在执行的任务,返回未执行的任务列表,第二次再调用shutDown
                    不会返回未执行的任务列表,当前执行器会变为空,因为线程池已经关闭了
                     */
                System.out.println("=========currentExecutor"+currentExecutor);
                List<Runnable> runnables = currentExecutor.shutdownNow();
                System.out.println("==========="+runnables);
                for (Runnable r : runnables) {
                    System.out.println("=========未执行的任务信息"+r.toString());
                }
                System.out.println("=========isShoutDown"+currentExecutor.isShutdown());
                currentExecutor = null;
            }
            //以第二项为例进行测试
            PoolTask poolTask = mPoolTasks.get(1);
            if (position == 1) {
                if (!isClick) {
                    poolTask.cancel(true);
                    isCancel = true;
                    isClick = !isClick;
                } else {
                    poolTask.cancel(false);
                    isCancel = false;
                    isClick = !isClick;
                    if (poolTask != null && poolTask.getStatus() == AsyncTask.Status.RUNNING) {
                        if (poolTask.isCancelled()) {
                            poolTask = new PoolTask(poolTask.itemview);
                        } else {
                            Toast.makeText(MainActivity.this, "任务已经在执行", Toast.LENGTH_SHORT).show();
                        }
                    }
                    if (currentExecutor == null) {
                        currentExecutor = Executors.newCachedThreadPool();
                    }
                    poolTask.executeOnExecutor(currentExecutor);//只能执行一次,也就是说第二个只能点击两次
                }
            } else {
                Toast.makeText(MainActivity.this, "其他的", Toast.LENGTH_SHORT).show();
                poolTask.cancel(false);
                isCancel =false;
            }
        }
    };

    class PoolTask extends AsyncTask<Void, Integer, Void> {
        private View itemview;
        private final TextView mTextView;
        private final ProgressBar mPb;
        private String id;
        public PoolTask(View itemview){
            this.itemview = itemview;
            mTextView = (TextView) itemview.findViewById(R.id.textview);
            mPb = (ProgressBar) itemview.findViewById(R.id.pb);
            if(order<count ||order == count){
                id = "执行:" + String.valueOf(++order);
            }else{
                order = 0;
                id = "执行:" + String.valueOf(++order);
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mTextView.setText(id);
        }

        @Override
        protected Void doInBackground(Void... params) {
            if(!isCancelled()&&isCancel == false){ //这个地方很关键,如果不设置标志位的话,直接setCancel(true)是无效的
                int prog = 0;
                while (prog<101){
                    if ((prog > 0 || prog == 0) && prog < 70) // 小于70%时,加快进度条更新
                    {
                        SystemClock.sleep(100);
                    }
                    else
                    // 大于70%时,减慢进度条更新
                    {
                        SystemClock.sleep(300);
                    }
                    publishProgress(prog); // 更新进度条
                    prog++;
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {//values是从publishProgress方法传过来的
            super.onProgressUpdate(values);
            mPb.setProgress(values[0]);
        }
    }
    class ThreadPoolAdapter extends BaseAdapter{
        private Context mContext;
        private LayoutInflater mInflater;
        private int taskcount;
        public ThreadPoolAdapter(Context context,int taskCount){
            mContext = context;
            taskcount = taskCount;
            mInflater = LayoutInflater.from(mContext);
            mPoolTasks = new ArrayList<>();
        }
        @Override
        public int getCount() {
            return taskcount;
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                convertView = mInflater.inflate(R.layout.list_view_item,null);
                PoolTask poolTask = new PoolTask(convertView);
                //根据指定的执行器执行任务
                poolTask.executeOnExecutor(currentExecutor);
                mPoolTasks.add(poolTask);
            }
            return convertView;
        }
    }
}

效果二(Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现)

public class MainActivity extends AppCompatActivity {
    //线程池是否处于运行状态
    private boolean isRunning = true;
    //是否唤醒线程池工作
    private boolean isNotify = true;
    //在此类中使用同步锁时使用如下lock对象即可,官方推荐的,不推荐直接使用MainActivity.this类型的
    private Object lock = new Object();
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            mProgressBar.setProgress(msg.what);
        }
    };
    //任务执行队列
    private ConcurrentLinkedQueue<MyRunnable> taskQueue;
    //正在等待执行或者已经完成的任务队列,线程安全的(HashMap是线程不安全的)
    private ConcurrentHashMap<Future, MyRunnable> taskMap;
    //创建一个不限制大小的线程池 此类主要有以下好处 1,以共享的无界队列方式来运行这些线程. 2,执行效率高。
    // 3,在任意点,在大多数 nThreads 线程会处于处理任务的活动状态
    //4,如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
    private ExecutorService mCachedThreadPool;
    private ProgressBar mProgressBar;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
        taskQueue = new ConcurrentLinkedQueue<MyRunnable>();
        taskMap = new ConcurrentHashMap<Future, MyRunnable>();
        if (mCachedThreadPool == null) {
            mCachedThreadPool = Executors.newCachedThreadPool();
        }
    }

    public void click(View view) {
        switch (view.getId()) {
            case R.id.add:
                addTask(new MyRunnable(mHandler));
                break;
            case R.id.start:
                startTask();
                break;
            case R.id.cancel:
                cancelTask();
                break;
            case R.id.release:
                releaseTask();
                break;
            case R.id.reload:
                reloadTask(new MyRunnable(mHandler));
                break;
        }
    }

    public void addTask(final MyRunnable myRunnable){
        mHandler.sendEmptyMessage(0);
        if(mCachedThreadPool == null){
            mCachedThreadPool = Executors.newCachedThreadPool();
            notifyWork();
        }
        if(taskMap == null){
            taskMap = new ConcurrentHashMap<>();
        }
        if(taskQueue == null){
            taskQueue = new ConcurrentLinkedQueue<>();
        }

        mCachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                taskQueue.offer(myRunnable);//插入一个Runnable到任务队列
                notifyWork();
            }
        });
        Toast.makeText(MainActivity.this, "已添加一个新任务到线程池中 !",Toast.LENGTH_SHORT).show();
    }

    public void startTask(){
        if(mCachedThreadPool == null||taskMap == null||taskQueue == null){
            return;
        }
        mCachedThreadPool.execute(new Runnable() {
            private MyRunnable mMyRunnable;
            @Override
            public void run() {
                if(isRunning){
                    synchronized (lock){
                        mMyRunnable = taskQueue.poll();//从线程队列里面取出一个Runnable用来执行
                        if(mMyRunnable == null){
                            isNotify = true;
                        }
                    }
                    if(mMyRunnable!=null){
                        taskMap.put(mCachedThreadPool.submit(mMyRunnable),mMyRunnable);
                    }
                }
            }
        });
    }

    public void cancelTask(){
        Toast.makeText(this, "任务被取消", Toast.LENGTH_SHORT).show();
        for(MyRunnable mr:taskMap.values()){
            mr.setCancelTask(true);
        }
    }

    public void reloadTask(final MyRunnable myRunnable){
        mHandler.sendEmptyMessage(0);
        if(mCachedThreadPool == null){
            mCachedThreadPool = Executors.newCachedThreadPool();
            notifyWork();
        }
        if(taskMap == null){
            taskMap = new ConcurrentHashMap<>();
        }
        if(taskQueue == null){
            taskQueue = new ConcurrentLinkedQueue<>();
        }
        mCachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                //插入一个Runnable对象到任务队列
                taskQueue.offer(myRunnable);
                notifyWork();
            }
        });
        mCachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if(isRunning){
                    MyRunnable myRunnable = null;
                    synchronized (lock){
                        myRunnable = taskQueue.poll();
                        if(myRunnable == null){
                            isNotify = true;
                        }
                    }
                    if(myRunnable!=null){
                        taskMap.put(mCachedThreadPool.submit(myRunnable),myRunnable);
                    }
                }
            }
        });
    }

    public void releaseTask(){
        Toast.makeText(this, "释放资源", Toast.LENGTH_SHORT).show();
        mHandler.sendEmptyMessage(0);
        Iterator<Map.Entry<Future, MyRunnable>> iterator = taskMap.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<Future,MyRunnable> entry = iterator.next();
            Future future = entry.getKey();
            if(future == null){
                continue;
            }
            future.cancel(true);
            taskMap.remove(future);//移除键对应的值
        }
        if(mCachedThreadPool!=null){
            mCachedThreadPool.shutdown();//关闭执行器
        }
        mCachedThreadPool = null;
        taskMap = null;
        taskQueue = null;
    }

    public void notifyWork(){
        synchronized (lock){
            if(isNotify){
                lock.notifyAll();
                isNotify = !isNotify;
            }
        }
    }
}

最后给出一篇写的比较好的关于线程池介绍的文章
线程池的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值