博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android学习笔记之ExecutorService线程池的应用....
阅读量:6417 次
发布时间:2019-06-23

本文共 10038 字,大约阅读时间需要 33 分钟。

PS:转眼间就开学了...都不知道这个假期到底是怎么过去的....

 

学习内容:

ExecutorService线程池的应用...

1.如何创建线程池...

2.调用线程池的方法,获取线程执行完毕后的结果...

3.关闭线程...

 

  首先我们先了解一下到底什么是线程池,只有了解了其中的道理,我们才能够进行应用...java.util.concurrent.ExecutorService表述了异步执行的机制

  首先我们简单的举一个例子...

package executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Executor {    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        System.out.println("cc");        ExecutorService executorService=Executors.newFixedThreadPool(10);        executorService.execute(new Runnable() {                        @Override            public void run() {                // TODO Auto-generated method stub                while(true){                                        System.out.println("aa");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        });        System.out.println("bb");    }}

  这里我们指定了十个线程处于一个线程池内部,线程池的原理其实就是对多线程的一个管理,为了实现异步机制的一种方法,其实就是多个线程执行多个任务,最终这些线程通过线程池进行管理...不用手动去维护...一次可以处理多个任务,这样就可以迅速的进行相应...比如说一个网站成为了热点网站,那么对于大量的点击量,就必须要对每一次的点击做出迅速的处理,这样才能达到更好的交互效果...这样就需要多个线程去处理这些请求,以便能够更好的提供服务...

1. 简单的说一下如何创建线程池进行初始化....创建线程有几种常用方式...这里都是使用了Executors工厂来实例化对象,同时我们也可以根据需求自己去写一个ExecutorService...这几种常用的方法有一定的区别...

ExecutorService executorService1 = Executors.newSingleThreadExecutor();ExecutorService executorService2 = Executors.newFixedThreadPool(10);ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
ExecutorService executorService4 = Executors.newCacheThreadPool();
Executors.newSingleThreadExecutor()
单例线程,表示在任意的时间段内,线程池中只有一个线程在工作...
Executors.newCacheThreadPool()
缓存线程池,先查看线程池中是否有当前执行线程的缓存,如果有就resue(复用),如果没有,那么需要创建一个线程来完成当前的调用.并且这类线程池只能完成一些生存期很短的一些任务.并且这类线程池内部规定能resue(复用)的线程,空闲的时间不能超过60s,一旦超过了60s,就会被移出线程池.
 Executors.newFixedThreadPool(10) 固定型线程池,和newCacheThreadPool()差不多,也能够实现resue(复用),但是这个池子规定了线程的最大数量,也就是说当池子有空闲时,那么新的任务将会在空闲线程中被执行,一旦线程池内的线程都在进行工作,那么新的任务就必须等待线程池有空闲的时候才能够进入线程池,其他的任务继续排队等待.这类池子没有规定其空闲的时间到底有多长.这一类的池子更适用于服务器.
 Executors.newScheduledThreadPool(10)

调度型线程池,调度型线程池会根据Scheduled(任务列表)进行延迟执行,或者是进行周期性的执行.适用于一些周期性的工作.

 

 

 

 

 

 

 

 

 

 

   这就是线程池创建的几种方式...我们需要根据不同的需求来适当的选择到底使用哪种线程池...

2.那么创建了线程池以后就需要对线程池进行调用..将任务加载到其中...

i.ExecutorService.execute(Runnable);

  第一种调用方式...通过这种方式将线程任务加载到线程池当中...我们可以添加多个任务...贴上一个完整的代码...大家看一下代码的解释就明白到底是怎么回事了..不难理解...

package executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Executor {    /**     * @param args     *      */     public static void main(String[] args) {        // TODO Auto-generated method stub        ExecutorService executorService=Executors.newFixedThreadPool(2);//定义了线程池中最大存在的线程数目...                //添加了第一个任务...这个任务会一直被执行...        executorService.execute(new Runnable() {                        @Override            public void run() {                // TODO Auto-generated method stub                while(true){                                        System.out.println("aa");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        });                //添加第二个任务,被执行三次停止...        executorService.execute(new Runnable() {            @Override            public void run() {                // TODO Auto-generated method stub                int i=0;                while(true){                    i++;                    System.out.println("bb");                    if(i==3){                        break;                    }                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    }            }        });                /*         * @param         * 第三个任务...只有当第二个任务被执行三次之后才能被执行...         * 由于三次前,线程池已经满了,这个任务是轮不到被执行的..只能排队进行等待.          * 三次之后,第二个任务被终止,也就是线程池中出现了空闲的状态,所以这个任务将被放入到线程池中执行...         * */        executorService.execute(new Runnable() {                        @Override            public void run() {                // TODO Auto-generated method stub                while(true){                                        System.out.println("cc");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        });    }}

  ii.executorService.submit(Runnable) 第二种调用方式...这种方式与第一种的区别在于可以使用一个Future对象来判断当前的线程是否执行完毕...但是这种方法只能判断当前的线程是否执行完毕,无法返回数据信息...

Future future = executorService.submit(new Runnable() {    public void run() {        System.out.println("Asynchronous task");    }});//如果任务结束执行则返回 nullSystem.out.println("future.get()=" + future.get());

  iii.executorService.submit(Callable)...  第三种调用方式...这种调用方式与前一种有所不同,传递的参数为Callable对象,Callable与Runnbale很相似,但是Callable的call()方法可以返回数据信息...通过Future就能够获取到其中的信息..而Runnbale.run()方法时无法获取数据信息的....Future应用于多线程...可以获取call()方法返回的数据信息...其实他是一种模式,是为了性能优化而提供的一种思想...这里我就不说Future...

uture future = executorService.submit(new Callable(){    public Object call() throws Exception {        System.out.println("Asynchronous Callable");        return "Callable Result";    }});System.out.println("future.get() = " + future.get());//上述样例代码会输出如下结果: //Asynchronous Callable//future.get() = Callable Result

 iv.inVokeAny()...第四种调用方式...方法 invokeAny() 接收一个包含 Callable 对象的集合作为参数。调用该方法不会返回 Future 对象,而是返回集合中某一个 Callable 对象的结果,而且无法保证调用之后返回的结果是哪一个Callable,只知道它是这些 Callable 中一个执行结束的 Callable 对象...说实话这个方法我不知道它创建的目的到底是什么...这里执行后的结果是随机的...也就是输出是不固定的....

ExecutorService executorService = Executors.newSingleThreadExecutor();Set
> callables = new HashSet
>();callables.add(new Callable
() { public String call() throws Exception { return "Task 1"; }});callables.add(new Callable
() { public String call() throws Exception { return "Task 2"; }});callables.add(new Callable
() { public String call() throws Exception { return "Task 3"; }});String result = executorService.invokeAny(callables);System.out.println("result = " + result);

  v.inVokeAll()这个方法和上面不同的地方就在于它可以返回所有Callable的执行结果...获取到所有的执行结果,我们可以对其进行管理...相对而言,我觉得这个方法比上一个更实用吧...

ExecutorService executorService = Executors.newSingleThreadExecutor();Set
> callables = new HashSet
>();callables.add(new Callable
() { public String call() throws Exception { return "Task 1"; }});callables.add(new Callable
() { public String call() throws Exception { return "Task 2"; }});callables.add(new Callable
() { public String call() throws Exception { return "Task 3"; }});List
> futures = executorService.invokeAll(callables);for(Future
future : futures){ System.out.println("future.get = " + future.get());

3.线程池的关闭...

当我们不需要使用线程池的时候,我们需要对其进行关闭...有两种方法可以关闭掉线程池...

i.shutdown()...

  shutdown并不是直接关闭线程池,而是不再接受新的任务...如果线程池内有任务,那么把这些任务执行完毕后,关闭线程池....

ii.shutdownNow()

  这个方法表示不再接受新的任务,并把任务队列中的任务直接移出掉,如果有正在执行的,尝试进行停止...

大家自己试着运行下面的代码就了解其中到底是怎么回事了...

 

package executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Executor {    /**     * @param args     *      */        public static void main(String[] args) {        // TODO Auto-generated method stub        ExecutorService executorService=Executors.newFixedThreadPool(1);//定义了线程池中最大存在的线程数目...                //添加了第一个任务...这个执行三次停止...        executorService.execute(new Runnable() {                        @Override            public void run() {                // TODO Auto-generated method stub                int j=0;                while(true){                    j++;                    System.out.println("aa");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                    if(j==3){                        break;                    }                }            }        });                //添加第二个任务,由于使用executorService.shutdown(),由于它的加入是在这个方法调用之前的,因此这个任务也会被执行...        //如果我们使用了executorService.shutdownNow();方法,就算是他在之前加入的,由于调用了executorService.shutdownNow()方法        //那么这个任务将直接被移出队列并且不会被执行...        executorService.execute(new Runnable() {            @Override            public void run() {                // TODO Auto-generated method stub                int i=0;                while(true){                    i++;                    System.out.println("bb");                    if(i==3){                        break;                    }                }            }        });        executorService.shutdown();//这里无论使用了那种方法,都会抛出一个异常...        /*         * @param         * 第三个任务...只有当第二个任务被执行三次之后才能被执行...         * 由于三次前,线程池已经满了,这个任务是轮不到被执行的..只能排队进行等待.          * 三次之后,第二个任务被终止,也就是线程池中出现了空闲的状态,所以这个任务将被放入到线程池中执行...         * */        executorService.execute(new Runnable() {                        @Override            public void run() {                // TODO Auto-generated method stub                while(true){                                        System.out.println("cc");                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }        });    }}

 

 

 

 

 

 

 

 

 

 

 

 

转载地址:http://ljpra.baihongyu.com/

你可能感兴趣的文章
网关支付、银联代扣通道、快捷支付、银行卡支付分别是怎么样进行支付的?...
查看>>
大数据开发实战:Stream SQL实时开发一
查看>>
C++返回引用的函数例程
查看>>
dll 问题 (转)
查看>>
使用sql生成UUID
查看>>
mysql日期函数(转)
查看>>
REST API用得也痛苦
查看>>
test for windows live writer plugins
查看>>
Tiny210 U-BOOT(二)----配置时钟频率基本原理
查看>>
读javascript高级程序设计14-错误处理与调试
查看>>
代理模式
查看>>
javaweb学习总结(二十四)——jsp传统标签开发
查看>>
让script的type属性等于text/html
查看>>
[Docker] Docker Machine intro
查看>>
HA 高可用软件系统保养指南
查看>>
linux 文件系统sysvinit 流程分析
查看>>
体素科技:2018年,算法驱动下的医学影像分析进展
查看>>
Vue 折腾记 - (8) 写一个挺靠谱的多地区选择组件
查看>>
VS Code折腾记 - (3) 多图解VSCode基础功能
查看>>
再不懂区块链,你就OUT了!
查看>>