java.util.concurrent.ExecutorService接口提供了许多线程管理的方法

Method 说明
shutdown 拒绝接收新的任务,待已提交的任务执行后关闭,且宿主线程不阻塞,若需要阻塞可借助awaitTermination实现
shutdownNow 停止所有正在执行的任务,挂起未执行的任务并关闭,且宿主线程不阻塞,若需要阻塞可借助awaitTermination实现
awaitTermination 当发生shutdown时,阻塞宿主线程直到约定的时间已过或者所有任务完成
submit 提交任务Callable/Runnable,可利用Future的get()方法使宿主线程阻塞直到任务结束后返回结果

有了以上方法,便可以基于此接口实现线程池的各种功能(例如java.util.concurrent.ThreadPoolExecutor/java.util.concurrent.ScheduledThreadPoolExecutor),以java.util.concurrent.ThreadPoolExecutor为例,其参数的详解

Name Type 说明
corePoolSize int 线程池中最小的线程数
maximumPoolSize int 线程池中最大的线程数
keepAliveTime long 线程空闲时间,若线程数大于corePoolSize,空闲时间超过该值的线程将被终止回收
unit TimeUnit keepAliveTime的时间单位
workQueue BlockingQueue<Runnable> 已提交但未执行的任务队列
threadFactory ThreadFactory 创建新线程的工厂
handler RejectedExecutionHandler 当线程池或队列达到上限拒绝新任务抛出异常时的处理类

同时,java.util.concurrent.Executors类提供的常用方法有

Method 说明 基类
newFixedThreadPool 线程池中含固定数量的线程 基于java.util.concurrent.ThreadPoolExecutor类
newSingleThreadExecutor 线程池中仅含一个工作线程
newCachedThreadPool 按需创建线程,若线程池中无可用线程,则创建新的线程并加入,直到线程数达到上限值(Integer.MAX_VALUE)
newWorkStealingPool 按照可用CPU数创建线程池 基于java.util.concurrent.ForkJoinPool类

java.util.concurrent.ForkJoinPool类是Fork/Join框架的实现类,Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架,该类在有递归实现的场景有更优异的表现。

package com.concurrent.test;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import org.junit.Assert;
import org.junit.Test; /**
* 测试ExecutorService
*/
public class ThreadExecutorServiceTest {
private static final String THIS_IS_SHUTDOWN_WITH_AWAIT_TERMINATION = "This is shutdownWithAwaitTermination";
private static final int RESULT = 111; private static boolean submitRunable() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<?> future = executorService.submit(new Runnable() { @Override
public void run() {
System.out.println("This is submitRunnable");
}
}); return future.get() == null;
} private static Integer submitRunnableWithResult() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(new Runnable() { @Override
public void run() {
System.out.println("This is submitRunnableWithResult");
}
}, RESULT); return future.get();
} private static Integer submitBlockCallable() throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("This is submitBlockCallable");
return RESULT;
}
});
return future.get(); //阻塞
} private static boolean submitNonBlockCallable() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("This is submitNonBlockCallable");
return RESULT;
}
}); while (!future.isDone()) {// 非阻塞
System.out.println(new Date());
} return future.isDone();
} private static String shutdown() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
final StringBuilder sb = new StringBuilder();
executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
sb.append("This is shutdown");
return RESULT;
}
});
executorService.shutdown();
return sb.toString();
} private static String shutdownWithAwaitTermination() throws InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
final StringBuilder sb = new StringBuilder();
executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
sb.append(THIS_IS_SHUTDOWN_WITH_AWAIT_TERMINATION);
return RESULT;
}
}); executorService.shutdown();
executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
return sb.toString();
} private static int testForkJoinPool(List<Integer> list) throws InterruptedException, ExecutionException {
ForkJoinPool forkJoinPool = new ForkJoinPool(8);
Future<Integer> future = forkJoinPool.submit(new SumTask(list));
return future.get();
} @Test
public void test() throws InterruptedException, ExecutionException {
Assert.assertTrue(submitRunable());
Assert.assertEquals(RESULT, submitRunnableWithResult().intValue());
Assert.assertEquals(RESULT, submitBlockCallable().intValue());
Assert.assertTrue(submitNonBlockCallable());
Assert.assertTrue(shutdown().isEmpty());
Assert.assertEquals(THIS_IS_SHUTDOWN_WITH_AWAIT_TERMINATION, shutdownWithAwaitTermination()); Assert.assertEquals(10, testForkJoinPool(Arrays.asList(new Integer[] { 1, 2, 3, 4 })));
Assert.assertEquals(49, testForkJoinPool(Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 })));
Assert.assertEquals(60, testForkJoinPool(Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }))); }
}

SumTask类如下:

package com.concurrent.test;

import java.util.List;
import java.util.concurrent.RecursiveTask; public class SumTask extends RecursiveTask<Integer> { /**
*
*/
private static final long serialVersionUID = -5468389855825594053L; private List<Integer> list; public SumTask(List<Integer> list) {
this.list = list;
} /*
* Ensure it is necessary to divide the job to parts and finish them separately
*/
@Override
protected Integer compute() {
int rtn , size = list.size();
if (size < 10) {
rtn = sum(list);
}
else{
SumTask subTask1 = new SumTask(list.subList(0, size /2));
SumTask subTask2 = new SumTask(list.subList(size /2 + 1, size));
subTask1.fork();
subTask2.fork();
rtn = subTask1.join() + subTask2.join();
}
return rtn; } private int sum(List<Integer> list) {
int sum = 0;
for (Integer integer : list) {
sum += integer;
}
return sum;
} }

【Java多线程系列七】ExecutorService的更多相关文章

  1. Java多线程系列七——ExecutorService

    java.util.concurrent.ExecutorService接口提供了许多线程管理的方法 Method 说明 shutdown 拒绝接收新的任务,待已提交的任务执行后关闭,且宿主线程不阻塞 ...

  2. java多线程系列(七)---Callable、Future和FutureTask

    Callable.Future和FutureTask 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量 ...

  3. (Java多线程系列七)Java内存模型和线程的三大特性

    Java内存模型和线程的三大特性 多线程有三大特性:原子性.可见性.有序性 1.Java内存模型 Java内存模型(Java Memory Model ,JMM),决定一个线程对共享变量的写入时,能对 ...

  4. java多线程系列(八)---CountDownLatch和CyclicBarrie

    CountDownLatch 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线 ...

  5. java多线程系列(九)---ArrayBlockingQueue源码分析

    java多线程系列(九)---ArrayBlockingQueue源码分析 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 j ...

  6. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  7. Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

    概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...

  8. Java多线程系列--“JUC线程池”01之 线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...

  9. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

随机推荐

  1. USACO 6.1 章节

    Postal Vans 题目大意 4*n的网格,要经过所有点的有向有环,不重复经过点的路径总数 n<=1000 题解 显然 插头dp 以4为切面 问题是,会发现 超精度 解决呢要么实现高精度,要 ...

  2. MySQL事务的四种隔离级别

    事务的基本要素: 原子性(atomicity):事务开始后的全部操作, 要么全部执行成功,如果中间出现错误,事务回滚到事务开始前的状态. 一致性(Consistency):事务开始后,数据库的完整性约 ...

  3. CTU Open 2018 Lighting /// 组合数递推 二进制

    题目大意: 给定n k 给定一个数的二进制位a[] 求这个数加上 另一个二进制位<=n的数b 后 能得到多少个不同的 二进制位有k个1 的数 样例 input10 51000100111 out ...

  4. 【问题解决方案】单个文件夹嵌套时github仓库中最外层文件夹直接显示所有嵌套文件夹名的问题

    上传文件的时候遇到这样一个问题: 这么看着好像有什么问题,直觉不应该这么显示吧 折腾半天,从github新建了嵌套文件夹并同步到本地,然后从本地push了文件,结果依然显示是这样 好吧,那这个问题应该 ...

  5. 前端工程师的新选择WebApp

    作为新一代移动端应用分发入口,小程序的趋势明朗化,竞争也在急剧激烈化.战线从手机 QQ.QQ 浏览器.支付宝.手机淘宝,华为,小米等九家手机厂商推出“快应用”,再拉到了谷歌的 Instant App ...

  6. 第五组postmortem报告

    为期近半年的软工课程顺利收工了.这一个学期的网站制作中, 憧憬过.懊恼过.兴奋过,回顾整个制作过程,我们按老师的要求来一份验尸报告. 1. 每个成员在beta 阶段的实践和alpha 阶段有何改进? ...

  7. 常看 Shell: 文本文件操作

    文件显示和信息 wc wc 可以用于统计文件的行数和单词数. nl nl 在文件的每行内容前面加上行号. 基于行的操作 grep grep 用于筛选匹配特定字符的行. grep "Hello ...

  8. 一、Redis的安装

    1.下载.解压.编译.安装 # 下载地址 wget http://download.redis.io/redis-stable.tar.gz # 解压 tar xzf redis-stable.tar ...

  9. 错误描述:fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "stdafx.h"”?(转)

    错误分析: 此错误发生的原因是编译器在寻找预编译指示头文件(默认#include "stdafx.h")时,文件未预期结束.没有找到预编译指示信息的头文件"stdafx. ...

  10. 关于Linux_监控系统资源/性能命令_vmstat

    (系统资源查看命令-vmstat[监控系统资源命令])          command:vmstat  [刷新延时 刷新次数]   分解解析: procs:进程信息字段:              ...