android多线程之线程池

一.线程简介

在Android应用开发中在进行耗时操作时,此时就要用到线程,由于UI线程不能进行耗时操作,否则就会造成ANR,话不多说下面直接干货。

二.子线程中更新UI的原理

有时在子线程中执行完操作以后需要把结果回传到UI线程,但是由于异步操作,我们需要等待子线程执行完毕之后才更新UI,这时大家都会想到Handler ,Message这种消息传递机制进行线程的切换,
其中的源码我在这里不再的分析,但是线程切换最本质的地方如下代码:

  new Thread(new Runnable() {
            @Override
            public void run() {
                Looper looper = Looper.getMainLooper()
                looper.prepare();
                //执行UI操作
                looper.loop();
            }
        }).start();

其实Handle 消息机制最本质的就是利用Looper实现线程切换。

三.与多线程有关的方法

1.Callable

2.Future

3.FutureTask

4.Runnable

Runnable 在多线程中是最熟悉不过的,但是Runnable 和Future 可以应用在Thread中,而Callable和Future只能应用在线程中。下面看代码:

Runnable 接口

public interface Runnable {
    void run();
}

Runnable接口没有返回值

Callable 接口

public interface Callable<V> {
    V call() throws Exception;
}

Callable 接口与Runnable接口不同的是一个泛型接口,它有一个泛型V的call()方法的返回值,而Runnable里面的run()方法执行完没有返回值;

Future接口

public interface Future<V> {
    boolean cancel(boolean var1);
    //该任务是否取消
    boolean isCancelled();

    //该任务是否执行完成
    boolean isDone();

    //得到返回结果,会发生阻塞
    V get() throws InterruptedException, ExecutionException;

    V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}

相比于Callable 和Runnable ,Future提供了对执行任务的可控性,这样很大程度上方便对执行任务的操作。

FutureTask 类

public class FutureTask<V> implements RunnableFuture<V> {
    //代码省略
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

FutureTask 实现了Runnable,这就是为什么他能应用于Thread中,下面我们通过一个例子来说明他们的区别!

public class FutureDemo {

    static ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    public static void main(String[] args){
        testRunnable();
        testCallable();
        testFutureTask();

    }

    private static void testFutureTask() {
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return sum(5, 16);
            }
        });
        mExecutor.submit(futureTask);
        try {
            System.out.println("=========testFutureTask====="+futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testCallable() {
        Future<Integer> submit = mExecutor.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return sum(5, 16);
            }
        });
        try {
            System.out.println("=========testCallable====="+submit.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void testRunnable() {
        Future<?> submit = mExecutor.submit(new Runnable() {
            @Override
            public void run() {
                sum(5, 16);
            }
        });
        try {
            System.out.println("=========testRunnable====="+submit.get());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private static int sum(int a, int b){
        return a+b;
    }
}

下附输出结果

=========testRunnable=====null
=========testCallable=====21
=========testFutureTask=====21

通过这个demo正好验证上面的结果。

四.Android中的线程池

1.常规线程池

直接上代码

public class ThreadManager {
    //线程池中线程数
    private final int THREAD_FIXED = 10;
    //单例模式获取对象
    private static ThreadManager sInstance = null;
    //线程池
    private ExecutorService mExecutorService;

    private ThreadManager() {
        this.mExecutorService = Executors.newFixedThreadPool(THREAD_FIXED);
    }

    public static synchronized ThreadManager getInstance() {
        if (sInstance == null) {
            sInstance = new ThreadManager();
        }
        return sInstance;
    }
    //执行操作任务接口
    public void submit(Runnable task) {
        this.mExecutorService.submit(task);
    }

    public Future<Integer> submit(Callable<Integer> task) {
        return this.mExecutorService.submit(task);
    }

    //关闭执行任务
    public void shutdown() {
        if (!this.mExecutorService.isShutdown())
            this.mExecutorService.shutdownNow();
    }
}

2.阻塞线程池

利用生产者和消费者模式来实现,并加上拒绝策略实现阻塞。直接上代码。

public class ThreadPoolManager {

    //核心线程数
    private int corePoolSize = 4;
    //最大线程数
    private int maximumPoolSize = 10;
    //保持时间
    private long keepAliveTime =10;
    //时间单位
    private TimeUnit unit = TimeUnit.SECONDS;
    //阻塞线程队列
    private LinkedBlockingQueue<Runnable> workQueue =  new LinkedBlockingQueue<>();

    /**
     * 线程池,执行请求
     */
    private ThreadPoolExecutor threadPoolExecutor;

    private ThreadPoolManager(){
        this.threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
        //开启请求对列
        threadPoolExecutor.submit(runnable);
    }

    public static ThreadPoolManager getInstance(){
        return InstanceHolder.instance;
    }

    private static class InstanceHolder{
        private static ThreadPoolManager instance = new ThreadPoolManager();
    }

    /**
     * 暴露api,添加请求
     */
    public <T> void excute(FutureTask<T> futureTask){
       if(null != futureTask){
           try {
               workQueue.put(futureTask);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while(true){
                FutureTask futureTask = null;
                try {
                    //阻塞就在这里
                    futureTask = (FutureTask) workQueue.take();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //执行请求
                    if(null != futureTask){
                        threadPoolExecutor.execute(futureTask);
                    }
                }

            }
        }
    };
    /**
     * 拒绝策略,实现队列阻塞
     */
    private RejectedExecutionHandler handler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
            try {
                workQueue.put(new FutureTask<Object>(runnable,null));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    };

}

下面是调用方法

        ThreadPoolManager.getInstance().excute(new FutureTask<Object>(new Callable<Object>() {
            @Override
            public Object call() throws Exception {

                return null;
            }
        }));

执行流程如下:

1.创建ThreadPoolManager单例对象;

2.在构造方法里面就创建线程并且执行任务Runnable

3.Runnable里面就从队列里面取出任务,最后执行任务

4.excute()方法就是往队列里面添加任务.

到此android的线程池分析完毕;

逆风的方向,更适合飞翔

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值