Java中要使用线程池,可以使用ThreadPoolExecutor的构造函数直接创建线程池实例。具体使用方法可以参考上一篇Java线程池构造参数详解。但是,在Executors类中,我们为我们提供了创建公共线程池的方法。下面我们来了解下常用的四种:newFixedThreadPool首先我们看一下这个线程池的创建方法:publicstaticExecutorServicenewFixedThreadPool(intnThreads){returnnewThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue());}从构造方法可以看出,它创建了一个固定大小的线程池,每提交一个任务就创建一个线程,直到线程达到线程池的最大值nThreads.一旦线程池的大小达到最大值,当有新的任务提交时,就会被放入无界阻塞队列中。当一个线程空闲时,任务会被从队列中取出并继续执行。那么,如何使用newFixedThreadPool呢?让我们举个例子:publicclassOneMoreStudy{publicstaticvoidmain(String[]args){ExecutorServicefixedThreadPool=Executors.newFixedThreadPool(3);for(inti=0;i<5;i++){finalintindex=i;fixedThreadPool.execute(newRunnable(){@Overridepublicvoidrun(){try{SimpleDateFormatsdf=newSimpleDateFormat("HH:mm:ss");System.out.println("运行时间:"+sdf.format(newDate())+""+index);Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}}});}fixedThreadPool.shutdown();}}上面的例子创建了一个固定的一个线程池,大小为3,然后在线程池中提交了5个任务。当提交第4个任务时,由于线程池的大小已经达到3,前3个任务正在运行,所以第4个任务被放入队列等待空闲线程再次运行。运行结果如下(注意前3个任务和后2个任务的运行时间):Runningtime:08:09:021Runningtime:08:09:022Runningtime:08:09:020运行时间:08:09:044运行时间:08:09:043newCachedThreadPool首先看这个线程池的创建方法:publicstaticExecutorServicenewCachedThreadPool(){returnnewThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,newSynchronousQueue());从构造方法可以看出,它创建了一个可缓存的线程池。提交新任务时,如果有空闲线程,则直接处理该任务,如果没有空闲线程,则创建一个新线程来处理该任务,队列中不存储任何任务。线程池不限制线程池的大小。线程池的大小完全取决于操作系统(或JVM)可以创建的最大线程大小。如果线程空闲时间超过60秒,就会被回收。那么,如何使用newCachedThreadPool呢?让我们举个例子:publicclassOneMoreStudy{publicstaticvoidmain(String[]args){for(inti=0;i<5;i++){finalintindex=i;cachedThreadPool.execute(newRunnable(){@Overridepublicvoidrun(){try{SimpleDateFormatsdf=newSimpleDateFormat("HH:mm:ss");System.out.println("Runtime:"+sdf.format(newDate())+""+index);Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}}});}cachedThreadPool.shutdown();}}因为这个线程有一份新工作如果提交任务,会创建一个新的线程(当线程池中没有空闲线程时),不需要等待,所以5个提交任务的运行时间是一样的,运行结果都是如下:运行时间:08:45:182运行时间:08:45:181运行时间:08:45:183运行时间:08:45:184运行时间:08:45:180newSingleThreadExecutor首先看这个线程池的创建方法:publicstaticExecutorServicenewSingleThreadExecutor(){returnnewFinalizableDelegatedExecutorService(newThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue())));}从构造方法可以看出,它创建了一个单线程的线程池,它只会使用唯一的工作线程来执行任务,保证所有的任务都按照指定的顺序执行那么,如何使用newSingleThreadExecutor呢?让我们举个例子:publicclassOneMoreStudy{publicstaticvoidmain(String[]args){for(inti=0;i<5;i++){finalintindex=i;singleThreadExecutor.execute(newRunnable(){@Overridepublicvoidrun(){try{SimpleDateFormatsdf=newSimpleDateFormat("HH:mm:ss");System.out.println("Runtime:"+sdf.format(newDate())+""+index);Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}}});}singleThreadExecutor.shutdown();}}因为线程池类似于单线程执行,所以先执行上一个任务,然后顺序执行下一个任务。运行结果如下:运行时间:08:54:170运行时间:08:54:191运行时间:08:54:212运行时间:08:54:233运行时间:08:54:254部分同学可能会有疑问:既然类似于单线程执行,那么这个线程池还有存在的必要吗?这里的单线程执行指的是线程池内部。从线程池外部来看,主线程向线程池提交任务时并没有阻塞。它仍然是异步的。newScheduledThreadPool方法创建一个固定大小的线程池,支持定时和周期性的任务执行。先看定时执行的例子:ScheduledExecutorServicescheduledThreadPool=Executors.newScheduledThreadPool(3);System.out.println("提交时间:"+sdf.format(newDate()));scheduledThreadPool.schedule(newRunnable(){@Overridepublicvoidrun(){System.out.println("运行时间:"+sdf.format(newDate()));}},3,TimeUnit.SECONDS);scheduledThreadPool.shutdown();}}使用这个线程池的schedule方法,延时3秒后执行任务,运行结果如下:提交时间:09:11:39运行时间:09:11:42我们来看例子再次定期执行:publicclassOneMoreStudy{publicstaticvoidmain(String[]args){finalSimpleDateFormatsdf=newSimpleDateFormat("HH:mm:ss");ScheduledExecutorServicescheduledThreadPool=Executors.newScheduledThreadPool(3);系统输出文件rintln("提交时间:"+sdf.format(newDate()));scheduledThreadPool.scheduleAtFixedRate(newRunnable(){@Overridepublicvoidrun(){System.out.println("运行时间:"+sdf.format(newDate()));}},1,3,TimeUnit.SECONDS);线程.睡眠(10000);scheduledThreadPool.shutdown();}}使用线程池的scheduleAtFixedRate方法,每3秒执行一次任务,运行结果如下:提交时间:09:23:20运行时间:09:23:21运行时间:09:23:24运行时间:09:23:27