这套机制分离了任务的建立和执行。经过使用执行器,仅仅须要实现Runnable接口的对象,而后将这些对象发送给执行器便可。执行器经过建立所需线程,来负责这些Runnable对象的建立,实例化以及运行。可是执行器的功能不限于此,他使用了线程池来提升应用程序的性能。当发送一个任务给执行器时,执行器会尝试使用线程池中的线程来执行这个任务,避免了不断地建立和销毁线程而致使的性能降低。java
建立线程执行器web
使用执行器框架(Executor Framework)第一步是建立ThreadPoolExecutor对象。能够ThreadPoolExecutor类提供的四个构造器或者使用Executors的工厂类来建立ThreadPoolExecutor对象。
缓存
package com.packtpub.java7.concurrency.chapter4.recipe1.task; import java.util.Date; import java.util.concurrent.TimeUnit; /** * This class implements a concurrent task * */ public class Task implements Runnable { /** * The start date of the task */ private Date initDate; /** * The name of the task */ private String name; /** * Constructor of the class. Initializes the name of the task * @param name name asigned to the task */ public Task(String name){ initDate=new Date(); this.name=name; } /** * This method implements the execution of the task. Waits a random period of time and finish */ @Override public void run() { System.out.printf("%s: Task %s: Created on: %s\n",Thread.currentThread().getName(),name,initDate); System.out.printf("%s: Task %s: Started on: %s\n",Thread.currentThread().getName(),name,new Date()); try { Long duration=(long)(Math.random()*10); System.out.printf("%s: Task %s: Doing a task during %d seconds\n",Thread.currentThread().getName(),name,duration); TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("%s: Task %s: Finished on: %s\n",Thread.currentThread().getName(),name,new Date()); } }
package com.packtpub.java7.concurrency.chapter4.recipe1.task; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; /** * This class simulates a server, for example, a web server, that receives * requests and uses a ThreadPoolExecutor to execute those requests * */ public class Server { /** * ThreadPoolExecutors to manage the execution of the request */ private ThreadPoolExecutor executor; /** * Constructor of the class. Creates the executor object */ public Server(){ executor=(ThreadPoolExecutor)Executors.newCachedThreadPool(); } /** * This method is called when a request to the server is made. The * server uses the executor to execute the request that it receives * @param task The request made to the server */ public void executeTask(Task task){ System.out.printf("Server: A new task has arrived\n"); executor.execute(task); System.out.printf("Server: Pool Size: %d\n",executor.getPoolSize()); System.out.printf("Server: Active Count: %d\n",executor.getActiveCount()); System.out.printf("Server: Completed Tasks: %d\n",executor.getCompletedTaskCount()); } /** * This method shuts down the executor */ public void endServer() { executor.shutdown(); } }
package com.packtpub.java7.concurrency.chapter4.recipe1.core; import com.packtpub.java7.concurrency.chapter4.recipe1.task.Server; import com.packtpub.java7.concurrency.chapter4.recipe1.task.Task; /** * Main class of the example. Creates a server and 100 request of the Task class * that sends to the server * */ public class Main { /** * Main method of the example * @param args */ public static void main(String[] args) { // Create the server Server server=new Server(); // Send 100 request to the server and finish for (int i=0; i<100; i++){ Task task=new Task("Task "+i); server.executeTask(task); } server.endServer(); } }
若是须要执行新的任务,缓存线程池就会建立新线程;若是线程所运行的任务执行完成后而且这个线程可用,那么缓存线程池将会重用这些线程。线程的重用的优势是减小了建立新线程所花费的时间。然而,新任务固定会依赖线程来执行,所以缓存线程池也有缺点,若是发送过多的任务给执行器,系统的负荷将会过载。框架
PS:仅当线程的数量是合理的或者线程只会运行很短的时间,合适采用Executors工厂类的newCachedThreadPool()方法来建立执行器。dom
ThreadPoolExecutor类的重要特性是,一般须要显示地去结束他。
ide