在java类库中,任务执行的主要抽象不是Thread,而是Executor,将任务的提交过程和执行过程解耦
public interface Executor { void execute(Runnable command); }
public class RunMain implements Executor{ @Override public void execute(Runnable command) { new Thread(command).start(); } }
为了解决执行服务的生命周期问题,Executor扩展了ExecutorService接口
public interface ExecutorService extends Executor { void shutdown(); List<Runnable> shutdownNow(); boolean isShutdown(); boolean isTerminated(); boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; // ....其他任务提交的便利方法 }
- ExecutorService的生命周期有3种状态,运行、关闭、已终止。
- shutdown执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成
- shutdownNow方法将执行粗暴的关闭方式:它将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务
- 可以调用awaitTermination来等待ExecutorService到达终止状态,或者通过调用isTerminated来轮询ExecutorService是否已经终止
线程池:
newFixedThreadPool :创建一个固定长度的线程池,每当提交一任务就创建一个线程,知道达到线程池的最大数量(如果某个线程由于发生了未预期的Exception而结束,那么线程池会补充一个新的线程)
newCachedThreadPool:创建一个可缓存的线程池,如果线程池规模超过了处理需求时,那么将回收空闲的线程,而当需求增加时,则可以添加新的线程,线程池的规模不存在任何限制
newSingleThreadExecutor:单线程的Executor,如果这个线程结束会创建一个新的线程来替代,能确保依照在队列中的顺序来穿行执行
newScheduledThreadPool:创一个固定长度的线程池,而且以延迟或定时的方式来执行任务,用于替换Timer
import static java.util.concurrent.TimeUnit.SECONDS; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; public class TestScheduledThread { public static void main(String[] args) { final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); final Runnable beeper = new Runnable() { int count = 0; public void run() { System.out.println(new Date() + " beep " + (++count)); } }; // 1秒钟后运行,并每隔2秒运行一次 final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(beeper, 1, 2, SECONDS); // 2秒钟后运行,并每次在上次任务运行完后等待5秒后重新运行 final ScheduledFuture beeperHandle2 = scheduler.scheduleWithFixedDelay(beeper, 2, 5, SECONDS); // 30秒后结束关闭任务,并且关闭Scheduler scheduler.schedule(new Runnable() { public void run() { beeperHandle.cancel(true); beeperHandle2.cancel(true); scheduler.shutdown(); } }, 30, SECONDS); } }
Runnable 和 Callable 描述的都是抽象的计算任务,后者有返回值,并可能抛出一个异常
Executor执行的任务有4个生命周期阶段:创建、提交、开始和完成
ExecutorService中所有的submit方法豆浆返回一个Future,
Callable 与 Future接口
public interface Callable<V> { V call() throws Exception; } public interface Future<V> { /** * 试图取消对此任务的执行, * 如果任务已经启动,则mayInterruptIfRunning参数决定是否执行此任务的线程中断 * * 此方法返回后,后续调用isDone将始终返回true。 * 后续调用isCancelled将始终返回true * */ boolean cancel(boolean mayInterruptIfRunning); /** *如果这个任务被取消之前,正常完成。返回true */ boolean isCancelled(); boolean isDone(); /** * 等待计算完成,然后获取其结果 * @throws CancellationException * if the computation was cancelled * @throws ExecutionException * if the computation threw an exception * @throws InterruptedException * if the current thread was interrupted while waiting */ V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }CompletionService用于封装
public class RunMain implements Callable<String> { private int id; public RunMain(int i) { this.id = i; } public static void main(String[] args) throws Exception { ExecutorService service = Executors.newCachedThreadPool(); CompletionService<String> completion = new ExecutorCompletionService<String>(service); for (int i = 0; i < 10; i++) { completion.submit(new RunMain(i)); } for (int i = 0; i < 10; i++) { System.out.println(completion.take().get()); } service.shutdown(); } public String call() throws Exception { Integer time = (int) (Math.random() * 1000); try { System.out.println(this.id + " start"); Thread.sleep(time); System.out.println(this.id + " end"); } catch (Exception e) { e.printStackTrace(); } return this.id + ":" + time; } }