`
y806839048
  • 浏览: 1117122 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Executor介绍

阅读更多

Java中的线程即是工作单元也是执行机制,从JDK 5后,工作单元与执行机制被分离。工作单元包括Runnable和Callable,执行机制由JDK 5中增加的java.util.concurrent包中Executor框架提供。

HotSpot VM的线程模型中将java的线程映射为本地操作系统的线程,java线程的启动意味着一个本地操作系统线程的创建,而java线程的终止也就意味着对应的系统线程的回收。

 

Executor框架主要包含三个部分:

任务:包括Runnable和Callable,其中Runnable表示一个可以异步执行的任务,而Callable表示一个会产生结果的任务

任务的执行:包括Executor框架的核心接口Executor以及其子接口ExecutorService。在Executor框架中有两个关键类ThreadPoolExecutor和ScheduledThreadPoolExecutor实现了ExecutorService接口。

异步计算的结果:包括接口Future和其实现类FutureTask。

 

下面是对Executor框架中的一些关键接口与类的简介

 

Executor接口(java.util.concurrent.Executor)

它是Executor的基础与核心,其定义如下:

public interface Executor {
    void execute(Runnable command);
}

 

它包含了一个方法execute,参数为一个Runnable接口引用。

Executor接口将任务的提交与执行分离开来。

 

ThreadPoolExecutor类(java.util.concurrent.ThreadPoolExecutor)

它是线程池的核心实现类,用来执行被提交的任务。

它通常由工厂类Executors来创建,Executors可以创建SingleThreadExecutor,FixedThreadPool以及CachedThreadPool等不同的ThreadPoolExecutor。

 

SingleThreadExecutor使用单线程执行任务,Executors提供的API有如下两个

public static ExecutorService newSingleThreadExecutor();
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);

SingleThreadExecutor保证了任务执行的顺序,不会存在多线程活动。

 

 FixedThreadPool是使用固定线程数的线程池,Executors提供的API有如下两个

1 public static ExecutorService newFixedThreadPool(int nThreads);
2 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

FixedThreadPool满足了资源管理的需求,可以限制当前线程数量。适用于负载较重的服务器环境。

 

CachedThreadPool是无界线程池,Executors提供的API有如下两个

public static ExecutorService newCachedThreadPool();
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);

CachedThreadPool适用于执行很多短期异步任务的小程序,适用于负载较轻的服务器。

 

ScheduledThreadPoolExecutor类(java.util.concurrent.ScheduledThreadPoolExecutor)

它是ThreadPoolExecutor的子类且实现了ScheduledExecutorService接口,它可以在给定的延迟时间后执行命令,或者定期执行命令,它比Timer更强大更灵活。

 Executors可以创建的ScheduledThreadPoolExecutor的类型有ScheduledThreadPoolExecutor和SingleThreadScheduledExecutor等

 

ScheduledThreadPoolExecutor具有固定线程个数,适用于需要多个后台线程执行周期任务,并且为了满足资源管理需求而限制后台线程数量的场景,Executors中提供的API有如下两个:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

 

SingleThreadScheduledExecutor具有单个线程,Executors提供的创建API有如下两个:

public static ScheduledExecutorService newSingleThreadScheduledExecutor();
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory);

它适用于单个后台线程执行周期任务,并且保证顺序一致执行的场景。

 

上述的ThreadPoolExecutor和ScheduledThreadPoolExecutor都可以用于执行Runnable与Callable接口的实现类

 

 

Future接口(Java.concurrent.Future)

Future代表着提交的任务的计算状态与结果,可以对其进行取消,查询是否取消,查询是否完成,查询结果等操作。

首先来看一下Future接口的定义:

复制代码
public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;

}
复制代码

 

FutureTask类间接实现了Future接口,它用来表示异步计算的结果。当ThreadPoolExecutor或者ScheduledThreadPoolExecutor执行Runnable接口或者Callable接口的实现类时,它们会返回一个Future接口引用(实现类为FutureTask)。

 

 Runnable接口或者Callable接口的实现类在被上述两者执行的区别是,前者没有返回结果,而后者可以返回结果。Runnable可以通过Executors提供的API(Executors#callable)包装为Callable。

 

 

 

 

本文参考资料:《Java并发编程的艺术》以及其他网上文档 

 

-----------------------------------------------------------------------------------------------------------------

下面是一些简单的Demo程序

复制代码
 1 import java.util.concurrent.Executor;
 2 import java.util.concurrent.Executors;
 3 
 4 public class ExecutorTest {
 5     public static void main(String[] args) {
 6 
 7         Runnable hello = () -> {
 8             for (int i = 0; i < 100; i++) {
 9                 System.out.println(i + " hello");
10             }
11         };
12         Runnable bye = () -> {
13             for (int i = 0; i < 100; i++) {
14                 System.out.println(i + " bye");
15             }
16         };
17 
18         Executor executor = Executors.newCachedThreadPool();
19 
20         executor.execute(hello);
21         executor.execute(bye);
22 
23     }
24 }
复制代码

上面程序使用了两个Runnable任务hello和bye来打印相应语句,程序将会交错打印hello和bye。如果将executor改为SingleThreadExecutor,将会先打印100个"hello",再打印100个"bye"。

 

复制代码
 1 import java.util.ArrayList;
 2 import java.util.List;
 3 import java.util.Random;
 4 import java.util.concurrent.Callable;
 5 import java.util.concurrent.ExecutionException;
 6 import java.util.concurrent.ExecutorService;
 7 import java.util.concurrent.Executors;
 8 import java.util.concurrent.Future;
 9 
10 public class ExecutorTest {
11     public static void main(String[] args) {
12         Random random = new Random();
13         List<Integer> numbers = new ArrayList<>();
14         for (int i = 0; i < 100000; i++) {
15             numbers.add(random.nextInt(100000));
16         }
17         int result = calculate(numbers, 3);
18         System.out.println(result);
19     }
20 
21     public static int calculate(List<Integer> numbers,int digit) {
22         List<Callable<Integer>> tasks = new ArrayList<>();
23         for (Integer x : numbers) {
24             tasks.add(() -> {
25                 int count=0;
26                 int y=x;
27                 do {
28                     if (y % 10 == digit) {
29                         count++;
30                     }
31                     y /= 10;
32                 } while (y > 0);
33                 return count;
34             });
35         }
36         ExecutorService service = Executors.newFixedThreadPool(10);
37         int answer=0;
38         try {
39             List<Future<Integer>> results = service.invokeAll(tasks);
40             for (Future<Integer> result : results) {
41                 try {
42                     answer+=result.get();
43                 } catch (ExecutionException e) {
44                     e.printStackTrace();
45                 }
46             }
47         } catch (InterruptedException e) {
48             e.printStackTrace();
49         }
50         return answer;
51     }
52 }
复制代码

上面的程序随机生成了100000个随机数,然后统计这些数字中每个数字10进制中具有多少个数位3的数量和。使用具有10个线程的线程池进行计算,最终通过Future引用对象的结果来统计答案。

分享到:
评论

相关推荐

    spark:Executor分配详解

    本文详细介绍了Spark集群中Executor的分配机制及其在资源管理和数据处理方面的作用。合理的Executor配置不仅可以提高任务执行效率,还能有效避免资源浪费和性能瓶颈问题。在实际部署Spark集群时,开发者应该根据具体...

    1、azkaban介绍、三种(solo-server、two-server和multiple-executor)部署方式及验证

    3. Multiple-Executor Mode:在大型或分布式环境中使用,Web Server和多个Executor Server分布在不同的机器上,同样使用MySQL数据库,提供更高的可扩展性和容错性。 部署Azkaban的Solo Server模式通常涉及以下几个...

    azkaban 3.4 编译后安装文件,分布式多executor(赠送安装文档)

    7. **客户端使用**:介绍如何使用Azkaban的Web界面提交作业,或者通过命令行工具(如`azkaban-client`)进行交互。 8. **监控与日志**:阐述如何查看Azkaban的运行状态,包括作业执行情况、错误日志、性能指标等。 ...

    Java Executor 框架的实例详解

    一、Executor 框架的介绍 Executor 框架是 Java 中一个高级的并发编程模型,提供了一种标准的方式来提交和执行任务。Executor 框架的主要组件包括 Executor 接口、ExecutorService 接口、ThreadPoolExecutor 类、...

    go-executor-example-master

    总的来说,"go-executor-example-master" 是一个全面介绍如何在 Go 中构建执行器的项目,涵盖了从基本的进程管理到高级的并发和错误处理策略等多个方面。通过这个项目,开发者可以学习到 Go 语言在实现这类系统级...

    Console Process Executor

    这段代码介绍了如何在Java中调用操作系统中的可执行命令,产将其标准输出及错误输出保存在文件中。

    针对于Executor框架,Java API,线程共享数据

    下面将详细介绍使用Executor框架的主要好处: - **简化线程管理**:Executor框架简化了线程的创建和管理过程。开发者无需关心底层的线程细节,只需关注任务的提交和执行即可。这极大地降低了多线程编程的难度。 - *...

    并发编程实践,全面介绍基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具、Executor部分等

    本文将全面介绍Java并发编程的基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具以及Executor服务。 1. **基础知识** - **并发与并行**:并发是指多个任务在同一时间段内交替执行,...

    Azkaban报错-azkaban.executor.ExecutorManagerException: No active executors found

    主要介绍了Azkaban报错-azkaban.executor.ExecutorManagerException: No active executors found,本文给大家介绍的非常详细,需要的朋友可以参考下

    MacroExecutor使用手册.xdf

    Macro Executor程式设计简介手册,介绍了软件的基本使用及安装过程,有简单的例子可供参考,只是大体介绍

    Redis 中spark参数executor-cores引起的异常解决办法

    主要介绍了Redis 中spark参数executor-cores引起的异常解决办法的相关资料,需要的朋友可以参考下

    Mybatis原始执行方式Executor代码实例解析

    在本文中,我们将详细介绍Mybatis原始执行方式Executor代码实例解析,包括Executor的分类和使用示例。 Executor分类 ---------- Mybatis提供了四种类型的Executor,每种类型都有其特点和应用场景。 ### 1. ...

    SQL File Executor-开源

    今天我们要介绍的是"SQL File Executor",一个开源的、专为执行SQL语句文件设计的小巧应用。这个工具以其简洁的界面和实用的功能,为自动化数据库创建和初始表内容加载提供了便利。 SQL File Executor的主要功能...

    大数据技术之Spark优化

    本文将详细介绍 Spark 优化技术的相关知识点。 资源配置 在 Spark 中,资源配置是性能调优的第一步。为任务分配更多的资源,可以提高 Spark 应用的性能。在 Spark 中,可以配置的资源包括 Executor 的数量、Driver...

    java中Executor,ExecutorService,ThreadPoolExecutor详解

    主要介绍了java中Executor,ExecutorService,ThreadPoolExecutor详解的相关资料,需要的朋友可以参考下

    0438-如何指定Spark1作业中Driver和Executor使用指定范围内端口

    温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原...在前面Fayson介绍了《如何指定Spark2作业中Driver和Executor使用指定范围内端口》,本篇文章Fayson主要介绍如何指定Spark

    ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍

    ThreadPoolExecutor的使用和Android常见的4种线程池使用介绍

    Spark原理及源码剖析1

    本文将深入探讨Spark的原理及源码分析,首先从Spark运行时的通用流程入手,然后介绍核心组件的角色与职责,以及Spark支持的不同集群部署模式。 在Spark的运行流程中,用户通过`spark-submit`提交应用程序。这个过程...

    spark调优介绍

    以下将详细介绍这些调优策略。 一、Spark开发代码调优 1. 减少行动操作:Spark的工作模式基于懒惰执行,只有遇到行动操作(如collect、save)时才会触发计算。因此,尽量减少不必要的行动操作,避免频繁触发计算,...

Global site tag (gtag.js) - Google Analytics