Executor API的相关介绍能够在由Oracle维护的Java SE文档——High Level Concurrency Objects中找到。Executor API向开发者提供一系列的对象实现高效的线程管理。一般来讲,这种高效是由一些线程池机制提供的。 html
线程池 java
线程池负责建立特定数量的工做线程,并在这些工做线程上运行用户自定义的任务。在这种机制下,最多可运行的用户自定义任务的数量由线程池的大小和系统资源的利用率决定。 服务器
左侧的代码想用for循环方式在你的程序中建立并执行5000个任务。在不使用线程池的状况下,试图激活这5000个任务将会对系统资源形成威胁。经过查看系统中正在运行的程序内活跃任务(线程)的数量,咱们能够更好地来理解威胁的含义。例如,上图显示了在个人机器上同时运行的一系列进程及其所持有的线程。咱们能够清楚的看到应用程序idea.exe持有71个线程,而其余的应用程序则使用了较少的线程。所以,若是我有5000个任务而且为这5000个任务建立了5000个不一样的线程,这难道意味着我设计了一个好的架构吗?(固然不是)事实上,若是我把这5000个任务按照必定规则(随机分配或按优先级分配)安排在特定数量的工做线程上运行,会更高效地利用系统资源并且不会给系统带来没必要要的压力。因为上面的图中设定了5个工做线程,这5000个任务在操做系统看来最多只有5个用户自定义任务在运行。当一个工做线程执行结束后,会从当前处于等待状态的任务中选取一个执行,这个过程会持续进行直到全部的任务都执行完成。所以,Java SE 1.5版本推出的Executor API的基本原理是经过提供多种线程池环境实现高效的线程管理。工做线程是线程工厂生产的通用线程。ExecutorService和ScheduledExecutorService是Executor API中的基本接口。这些接口的实现多是Executors类的一系列静态方法。Java EE 7版本推出的新Concurrency Utilities标准经过容器服务提供这些对象的注入和管理。容器管理的Executor对象以XXXExecutorService和XXXScheduledExecutorService的形式命名,如ManagedExecutorService和ManagedScheduledExecutorService标识了它是可管理的。你能够查看这些接口的UML图,了解Java SE Executor API接口间的继承关系。 架构
以“Managed”开头的接口基本上和Java 1.5版本推出的Executor API组件提供相同的操做。不一样之处在于,其建立的对象将以容器资源(container resources)的形式提供给开发者。 并发
容器资源是由应用服务器管理的特殊对象。DataSources、JMS resources以及Concurrency Utilities中的Concurrency units都属于容器资源。 oracle
容器资源是驻留在应用服务器上并提供特定功能的对象。这些对象能够经过 JNDI( Java Naming and Directory Interfaces )标准进行访问 。@Resource 注解和 Context接口类型的对象(如:InitialContext)基本上能够实现对这些对象的访问。
建立并发资源 java-ee
支持Java EE 7版本的应用服务器可以建立Concurrency Utilities中可管理的Executor对象。例如,这个建立过程能够经过Glassfish 4的asadmin命令集或者Glassfish管理员控制台直观地定义出来。 ide
Glassfish应用服务器/bin目录下的asadmin tool用于命令行操做。下面的例子使用了asadmin tool,并经过create-managed-executor-service 命令和create-managed-scheduled-executor-service命令建立可管理的Executor对象。由于容器资源在被提供给应用环境时携带着听从JNDI标准定义的访问表达式,因此须要在控制台中输入表明该容器资源的惟一访问标识符。 url
在Glassfish管理员控制台中可以看到可管理的Executor对象。与此同时,在管理员控制台中也可以进行添加和修改。 idea
Glassfish 4的容器资源显示在控制台的Resources标签下。并发资源显示在子标签Concurrent Resources下。而咱们建立的用于容器管理的ManagedExecutorService和ScheduledManagedExecutorService 资源就能在这个子标签下找到。由应用服务器内部定义的带__default前缀的并发资源也是可用的。若是须要的话,也可使用现有的默认资源。
获取Concurrency Utilities中的资源
注入的@Resource注解和InitialContext对象可以访问驻留在应用服务器上的并发资源。@Resource 注解和InitialContext对象提供标准的JNDI访问不只适用于并发资源,还适用于其余容器资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@WebServlet(urlPatterns ="/kodcu",name ="KodcuServlet")
publicclassKodcuServletextendsHttpServlet {
@Resource// (1)
privateManagedExecutorService defaultmanagedExecutorService;
@Resource// (2)
privateManagedScheduledExecutorService defaultScheduledExecutorService;
@Resource(lookup ="concurrent/KodcuExecutor")// (3)
privateManagedExecutorService managedExecutorService;
@Resource(lookup ="concurrent/KodcuScheduledExecutor")// (4)
privateManagedScheduledExecutorService scheduledExecutorService;
@Override
protectedvoiddoGet(HttpServletRequest req, HttpServletResponse resp)throwsServletException, IOException {
...
InitialContext context=newInitialContext();// (5)
ManagedExecutorService managedExecutorServiceWithContext = (ManagedExecutorService) context.lookup("concurrent/KodcuExecutor");
...
}
}
|
上面的Servlet类,使用@Resource注解获取默认的并发资源(编号1和编号2)以及在命令行中指定特定JNDI名称所建立的并发资源(编号3和编号4)。@Resource注解的lookup字段存放着相应对象的惟一资源访问标识符,该标识符听从JNDI标准。当@Resource注解没有设定lookup字段时,注入的是带有__default前缀的默认JNDI资源。除了使用注解的方法以外,在编号5的代码段中,使用InitialContext对象根据JNDI名称获取相应的并发资源。
本文的示例源码连接以下:
http://en.kodcu.com/2013/10/java-ee-7-concurrency-utilities-spesification/