Executors创建的4种线程池的使用
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
注意:线程池只是为了控制应用中处理某项业务中防止高并发问题带来的线程不安全的发生的概率。在我目前的测试用,还没有发现线程可以重用这个概念,因为线程开启后,用完就关闭了,不可以再次开启的,查看源码发现会每次新创建一个线程用来处理业务。我们可以通过线程池指定处理这项业务最大的同步线程数,比如:Executors.newFixedThreadPool(3);在线程池中保持三个线程可以同时执行,但是注意,并不是说线程池中永远都是这三个线程,只是说可以同时存在的线程数,当某个线程执行结束后,会有新的线程进来。newFixedThreadPool.execute(newThreadForpools());这句话的含义并不是添加新的线程,而是添加新的处理业务请求进来。至少我当前是这么理解的,没有发现线程可以重复使用。
处理线程代码:
package com.alivn.sockets; /** * Created by Alivn on 2017/3/19. */ public class ThreadForpools implements Runnable{ private Integer index; public ThreadForpools(Integer index) { this.index=index; } @Override public void run() { /*** * 业务......省略 */ try { System.out.println("开始处理线程!!!"); Thread.sleep(index*100); System.out.println("我的线程标识是:"+this.toString()); } catch (InterruptedException e) { e.printStackTrace(); } } }
(1) newCachedThreadPool
创建一个可缓存线程池,应用中存在的线程数可以无限大
示例代码如下:
package com.alivn.sockets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Alivn on 2017/3/19. */ public class Threadpools { /** * 我们获取四次次线程,观察4个线程地址 * @param args */ public static void main(String[]args) { ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); System.out.println("****************************newCachedThreadPool*******************************"); for(int i=0;i<4;i++) { final int index=i; newCachedThreadPool.execute(new ThreadForpools(index)); } } }
输出结果是:可以有无限大的线程数进来(线程地址不一样)
(2) newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
package com.alivn.sockets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by Alivn on 2017/3/19. */ public class Threadpools { /** * 我们获取四次次线程,观察4个线程地址 * @param args */ public static void main(String[]args) { //线程池允许同时存在两个线程 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2); System.out.println("****************************newFixedThreadPool*******************************"); for(int i=0;i<4;i++) { final int index=i; newFixedThreadPool.execute(new ThreadForpools(index)); } } }
输出结果:每次只有两个线程在处理,当第一个线程执行完毕后,新的线程进来开始处理(线程地址不一样)
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:
package com.alivn.sockets; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Created by Alivn on 2017/3/19. */ public class Threadpools { /** * 我们获取四次次线程,观察4个线程地址 * @param args */ public static void main(String[]args) { ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2); System.out.println("****************************newFixedThreadPool*******************************"); for(int i=0;i<4;i++) { final int index=i; //延迟三秒执行 newScheduledThreadPool.schedule(new ThreadForpools(index),3, TimeUnit.SECONDS); } } }
执行结果:延迟三秒之后执行,除了延迟执行之外和newFixedThreadPool基本相同,可以用来执行定时任务
4) newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:
package com.alivn.sockets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Created by Alivn on 2017/3/19. */ public class Threadpools { /** * 我们获取四次次线程,观察4个线程地址 * @param args */ public static void main(String[]args) { ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); System.out.println("****************************newFixedThreadPool*******************************"); for(int i=0;i<4;i++) { final int index=i; newSingleThreadExecutor.execute(new ThreadForpools(index)); } } }
执行结果:只存在一个线程,顺序执行