Java并发编程-Executor框架

时间:2022-04-04 23:39:21

我们在传统多线程编程创建线程时,常常是创建一些Runnable对象,然后创建对应的Thread对象执行它们,但是如果程序需要并发执行大量的任务时,需要为每个任务都创建一个Thread,进行管理,这将会影响程序的执行效率,并且创建线程过多将会使系统负载过重。

在JDK 1.5之后通过了一套Executor框架能够解决这些问题,能够分解任务的创建和执行过程。该框架包括Executor,ExecutorService,Callable等基础接口和Executors,ThreadPoolExecutor等实现类。

Executor框架类图:
(图片转自http://www.javaclubcn.com/a/jichuzhishi/2012/1116/170.html)
Java并发编程-Executor框架

创建线程池:

Executor框架的最核心的类是ThreadPoolExecutor,它是线程池的实现类,创建ThreadPoolExecutor一般使用Executors工厂模式创建,Executors类提供了一系列工厂方法用于创先线程池:

  • public static ExecutorService newFixedThreadPool(int nThreads)创建固定数目线程的线程池,表示最多创建nThreads个线程,如果传入的任务数大于nThreads时不会创建新的线程,而是阻塞等待有空闲线程执行。

  • public static ExecutorService newCachedThreadPool()创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60秒钟未被使用的线程。

  • public static ExecutorService newSingleThreadExecutor()创建一个单线程的Executor。

  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

常用方法:

  • shutDown():关闭执行器,在关闭前允许执行以前提交的任务执行器执行完。调用shutDown()后,再发送任务给Executor将会被拒绝,抛出RejectExecutionException异常。

  • shutdownNow() :立即关闭执行器,阻止等待任务启动,并试图停止当前正在执行的任务。返回等待执行的任务列表。

  • isShutdown():调用shutDown()后,返回true。

  • isTerminated():调用shutDown()后,并且执行器完成了关闭过程,返回true。

  • getPoolSize():获取当前线程池的线程数量

  • getActiveCount():获取线程池中活动线程的数量

  • getCompleteCount():获取线程池中完成的任务数。

使用例子:

package MyThread;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ExecutorTest {
public static void main(String[] args){
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++){
executor.execute(new task());
}
executor.shutdown();
while(!executor.isTerminated()){
System.out.printf("Pool size:%d,Active count:%d,Completed Task:%d\n",executor.getPoolSize(),executor.getActiveCount(),executor.getCompletedTaskCount());
}
}

}
class task implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName() + " is called");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

结果:

pool-1-thread-2 is called
pool-1-thread-4 is called
pool-1-thread-5 is called
pool-1-thread-3 is called
pool-1-thread-1 is called
Pool size:5,Active count:5,Completed Task:0
Pool size:5,Active count:5,Completed Task:0
Pool size:5,Active count:5,Completed Task:0
Pool size:5,Active count:5,Completed Task:0