针对不同的情况,我们可以根据不同线程池的特性来实现不同的业务。那线程池总共分为哪几种呢?
(1)、newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
(2)、newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。(3)、newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
(4)、newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。(5)、newWorkStealingPool创建持有足够的线程的线程池来支持给定的并行级别,该方法还有使用多个队列来减少竞争。
newCachedThreadPool:
public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { System.out.println("put index="+index+"***"+new Date().getSeconds()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { public void run() { try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"***"+new Date().getSeconds()+"========"+index); } }); } }
从上图中,我们可以看到,此线程池的容量是可以自动无限扩大的,但是很明显,他也不会无缘无故的养活那么多闲人,当任务执行完成后,会复用已经存在的线程执行新的任务,不会每次都新建线程。
newFixedThreadPool
public static void main(String[] args) { ExecutorService fixedThreadPool=Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index=i; fixedThreadPool.execute(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()+"***"+new Date().getSeconds()+"====="+index); Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } }); } }
大家从此线程池的构造方法上应该也能看出来,他是可以创建定长线程池的,然后从图中可以看出,每次最多执行3个线程。注意:定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
newSingleThreadExecutor
public static void main(String[] args) { ExecutorService singleThreadPool=Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index=i; singleThreadPool.execute(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName()+"***"+new Date().getSeconds()+"====="+index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } }
这个就没有什么好解释的了吧!
newScheduledThreadPool
public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(3); System.out.println(new Date().getSeconds()); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"***"+new Date().getSeconds()+"===== I love LSR"); } },3,TimeUnit.SECONDS); }
图中我们可以看出来,初时是39秒点,执行任务是42秒点,正好延时3秒执行。
public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool=Executors.newScheduledThreadPool(3); System.out.println(new Date().getSeconds()); scheduledThreadPool.schedule(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"***"+new Date().getSeconds()+"===== I love LSR"); } },0,3,TimeUnit.SECONDS); }
这里不仅延时0秒点(设计失误,最好是能看出延时效果来),而且每3秒执行一次,也就是也用来执行定时和周期性任务。那我们能不能指定时间点去执行,而不是计算延时呢?答案是否定的!