留给开发者本身实现的接口,通常状况下不须要再去实现。它只有一个方法 java
void execute(Runnable command)
它继承自Executor接口,但多了以下3个功能 windows
1. <T> Future<T> submit(Callable<T> task) 2. Future<?> submit(Runnable task) 3. <T> Future<T> submit(Runnable task, T result)
Future<String> future = service.submit(task,"aaaa"); String s = future.get();// s="aaaa";
void submit(Runnable task)
这是由于Future除了get这种获取任务信息外,还能够控制任务,体如今 Future的这个方法上 性能优化
boolean cancel(boolean mayInterruptIfRunning)
这个方法的JavaDoc解释的很清楚 性能
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
注意:若是任务没执行完,这3种方式的Future.get()都会阻塞。 fetch
boolean awaitTermination(long timeout,TimeUnit unit)
好比 优化
service.shutdown(); service.awaitTermination(20, TimeUnit.SECONDS);
它的意思是,当service.shutdown()后,主线程阻塞,任务执行结束或者阻塞20秒之后,阻塞解除。 ui
它继承自ExecutorService接口。顾名思义,它主要用来按期执行任务或周期执行任务。它只有4个方法,都比较好理解。下面用最简单的例子来作个说明 this
scheduler.schedule(callable,10,SECONDS); //10秒后开始执行callable任务 scheduler.schedule(runnable,10,Seconds); //10秒后开始执行runnable任务 scheduler.scheduleAtFixedRate(runnable, 5, 10, SECONDS); //5秒后开始执行Runnable任务,而后每隔10秒执行一遍该任务. scheduler.scheduleWithFixedDelay(runnable,5,10,SECONDS); //5秒后开始执行Runnable任务,而后任务执行完后再等10秒就执行一遍任务,即,每隔任务执行的时间+10秒再执行一遍任务。
这4个方法都返回ScheduledFuture对象.它继承自Future接口,用途和Future差很少。 spa
在JDK以前,计划任务通常由java.until.Timer类来完成。但相比起 ScheduleExecutorService来讲,Timer类的功能较为简单,好比下例 线程
private final static long fONCE_PER_DAY = 1000*60*60*24; Timer timer = new Timer(); timer.scheduleAtFixedRate(fetchMail, getTomorrowMorning4am(), fONCE_PER_DAY);
这个类是一个工厂类,用来生成不一样特色的ExecutorService或 ScheduledExecutorService实例。这里主要介绍这些不一样特色的实例不一样在什么地方。
static ExecutorService newSingleThreadExecutor()
启动一个线程负责任务顺序执行,顺序意味着先提交的任务先执行。其原理是:任务会被提交到一个队列里,启动的那个线程会从队里里取任务,而后执行,执行完,再从队列里取下一个任务,再执行。若是该线程执行一个任务失败,并致使线程结束,系统会建立一个新的线程去执行队里里后续的任务,不会由于前面的任务有异常致使后面无辜的任务没法执行。
static ExecutorService newCachedThreadPool()
启动N个线程处理N个任务。既然是多个线程运行,意味着任务不会顺序运行。一个任务完成后,该线程空闲60秒会被结束。新提交的任务会发现空闲线程,并使用它,若是没有空闲线程可用则建立新线程。其实,这就是一个动态线程池。适合于规模比较小、建立较频繁的任务。
static ExecutorService newFixedThreadPool(int nThreads)
动态线程池不限制线程的数量,在有些状况下咱们不但愿线程数量不可控,则可使用拥有固定线程数目的线程池。运做原理是:任务被提交到一个队列里排队,线程池里的空闲线程会把队列里的任务提出来执行,每一个线程执行完一个任务后,就去队列里抓另外一个任务出来执行。若是一个线程因为失败而终止,系统会建立另外一个线程执行后续任务。
//你本身的实现 class YourselfThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { Thread thread = new Thread(r); doXXX; return thread; } }
JavaDoc上说:Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
((ThreadPoolExecutor)newFixedThreadPool(1)).setCorePoolSize(3);
即newFixedThreadPool(1)能够后期修改线程数,不能保证线程只有一个。而newSingleThreadExecutor能够保证。
把Runnable任务转换成Callable任务.例子以下
public static void test() throws Exception { Runnable task = new Runnable() { public void run() { log("begin task"); try { Thread.sleep(1000); } catch (InterruptedException e) { } log("end task"); } }; Callable c = Executors.callable(task); ExecutorService service = Executors.newCachedThreadPool(); Future f = service.submit(c); System.out.println(f.get());//返回null log("end"); } private static void log(String message) { System.out.println(new Date() + ": " + message); } public static void main(String args[]) throws Exception { test(); }