线程可以驱动任务,因此首先要定义任务。
定义任务只需要实现Runnable接口并编写run方法。但这样并不会产生任何内在的线程能力,要实现线程行为,必须显式地将一个任务附着到线程上。
有两种方式可以使任务附着在线程上:
①将Runnable对象附着在线程上的传统方式是将它提交给一个Thread类的构造器中。并调用start方法启动任务。任务的提交和执行是同时进行的,如果你想对任务的执行进行调度或是控制同时执行的线程数量就需要额外编写代码来完成
②使用Java SE5的java.util.concurrent包中的执行器(Executor)来管理Thread对象,是在Java SE5/6中启动任务的优选方法。
因为第一种方法较为简单,本篇文章重点关注第二种方法。
Executor架构主要有三个接口和其相应的具体类组成。这三个接口是 Executor, ExecutorService 和 ScheduledExecutorService
②ExecutorService 接口:
ExecutorService 继承了 Executor 的方法,并提供了执行 Callable 任务和中止任务执行的服务,其定义的方法主要有:
- submit(task):可用来提交Callable或Runnable任务,并返回代表此任务的Future对象
- invokeAll(collection of tasks):批处理任务集合,并返回一个代表这些任务的Future对象集合
- shutdown():在完成已提交的任务后关闭服务,不再接受新任务
- shutdownNow():停止所有正在执行的任务并关闭服务。
- isTerminated():测试是否所有任务都执行完毕了。
- isShutdown():测试是否该ExecutorService已被关闭
- schedule(task, initDelay): 安排所提交的Callable或Runnable任务在initDelay指定的时间后执行。
- scheduleAtFixedRate():安排所提交的Runnable任务按指定的间隔重复执行
- scheduleWithFixedDelay():安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行。
- callable(Runnable task): 将Runnable的任务转化成Callable的任务
- newSingleThreadExecutor: 生产一个ExecutorService对象,这个对象只有一个线程可用来执行任务,若任务多于一个,任务将按先后顺序执行。
- newCachedThreadPool(): 生产一个ExecutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用。
- newFixedThreadPool(int poolSize):生产一个ExecutorService对象,这个对象带有一个大小为poolSize的线程池,若任务数量大于poolSize,任务会被放在一个queue里顺序执行。
- newSingleThreadScheduledExecutor:生产一个ScheduledExecutorService对象,这个对象的线程池大小为1,若任务多于一个,任务将按先后顺序执行。
- newScheduledThreadPool(int poolSize): 生产一个ScheduledExecutorService对象,这个对象的线程池大小为poolSize,若任务数量大于poolSize,任务会在一个queue里等待执行
注意:任务写在run方法内,实现了Runnable接口。new Thread(Runnable r).start();使该线程开始执行,Java 虚拟机自动调用该线程的 run
方法。 exec.execute(Runnable r)底层是使用了Thread的start方法,因此Java虚拟机自动调用线程的run方法,Executor将任务提交和执行分离了,便于对Thread对象的管理。
参考:http://www.aiuxian.com/article/p-114878.html