java.util.concurrent简介

java.util.concurrent包提供了很多有用的类,方便我们进行并发程序的开发。本文将会做一个总体的简单介绍。

主要的组件

java.util.concurrent包含了很多内容, 本文将会挑选其中常用的一些类来进行大概的说明:

  • Executor
  • ExecutorService
  • ScheduledExecutorService
  • Future
  • CountDownLatch
  • CyclicBarrier
  • Semaphore
  • ThreadFactory

Executor

Executor是一个接口,它定义了一个execute方法,这个方法接收一个Runnable,并在其中调用Runnable的run方法。

我们看一个Executor的实现:

public class Invoker implements Executor {
@Override
public void execute(Runnable r) {
r.run();
}
}

现在我们可以直接调用该类中的方法:

    public void execute() {
Executor executor = new Invoker();
executor.execute( () -> {
log.info("{}", Thread.currentThread().toString());
});
}

注意,Executor并不一定要求执行的任务是异步的。

ExecutorService

如果我们真正的需要使用多线程的话,那么就需要用到ExecutorService了。

ExecutorService管理了一个内存的队列,并定时提交可用的线程。

我们首先定义一个Runnable类:

public class Task implements Runnable {
@Override
public void run() {
// task details
}
}

我们可以通过Executors来方便的创建ExecutorService:

ExecutorService executor = Executors.newFixedThreadPool(10);

上面创建了一个ThreadPool, 我们也可以创建单线程的ExecutorService:

ExecutorService executor =Executors.newSingleThreadExecutor();

我们这样提交task:

public void execute() {
executor.submit(new Task());
}

因为ExecutorService维持了一个队列,所以它不会自动关闭, 我们需要调用executor.shutdown() 或者executor.shutdownNow()来关闭它。

如果想要判断ExecutorService中的线程在收到shutdown请求后是否全部执行完毕,可以调用如下的方法:

try {
executor.awaitTermination( 5l, TimeUnit.SECONDS );
} catch (InterruptedException e) {
e.printStackTrace();
}

ScheduledExecutorService

ScheduledExecutorService和ExecutorService很类似,但是它可以周期性的执行任务。

我们这样创建ScheduledExecutorService:

ScheduledExecutorService executorService
= Executors.newSingleThreadScheduledExecutor();

executorService的schedule方法,可以传入Runnable也可以传入Callable:

Future<String> future = executorService.schedule(() -> {
// ...
return "Hello world";
}, 1, TimeUnit.SECONDS); ScheduledFuture<?> scheduledFuture = executorService.schedule(() -> {
// ...
}, 1, TimeUnit.SECONDS);

还有两个比较相近的方法:

scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit )

scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit )

两者的区别是前者的period是以任务开始时间来计算的,后者是以任务结束时间来计算。

Future

Future用来获取异步执行的结果。可以调用cancel(boolean mayInterruptIfRunning) 方法来取消线程的执行。

我们看下怎么得到一个Future对象:

public void invoke() {
ExecutorService executorService = Executors.newFixedThreadPool(10); Future<String> future = executorService.submit(() -> {
// ...
Thread.sleep(10000l);
return "Hello world";
});
}

我们看下怎么获取Future的结果:

if (future.isDone() && !future.isCancelled()) {
try {
str = future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}

future还可以接受一个时间参数,超过指定的时间,将会报TimeoutException。

try {
future.get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}

CountDownLatch

CountDownLatch是一个并发中很有用的类,CountDownLatch会初始化一个counter,通过这个counter变量,来控制资源的访问。我们会在后面的文章详细介绍。

CyclicBarrier

CyclicBarrier和CountDownLatch很类似。CyclicBarrier主要用于多个线程互相等待的情况,可以通过调用await() 方法等待,知道达到要等的数量。

public class Task implements Runnable {

    private CyclicBarrier barrier;

    public Task(CyclicBarrier barrier) {
this.barrier = barrier;
} @Override
public void run() {
try {
LOG.info(Thread.currentThread().getName() +
" is waiting");
barrier.await();
LOG.info(Thread.currentThread().getName() +
" is released");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
} }
public void start() {

    CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
// ...
LOG.info("All previous tasks are completed");
}); Thread t1 = new Thread(new Task(cyclicBarrier), "T1");
Thread t2 = new Thread(new Task(cyclicBarrier), "T2");
Thread t3 = new Thread(new Task(cyclicBarrier), "T3"); if (!cyclicBarrier.isBroken()) {
t1.start();
t2.start();
t3.start();
}
}

Semaphore

Semaphore包含了一定数量的许可证,通过获取许可证,从而获得对资源的访问权限。通过 tryAcquire()来获取许可,如果获取成功,许可证的数量将会减少。

一旦线程release()许可,许可的数量将会增加。

我们看下怎么使用:

static Semaphore semaphore = new Semaphore(10);

public void execute() throws InterruptedException {

    LOG.info("Available permit : " + semaphore.availablePermits());
LOG.info("Number of threads waiting to acquire: " +
semaphore.getQueueLength()); if (semaphore.tryAcquire()) {
try {
// ...
}
finally {
semaphore.release();
}
} }

ThreadFactory

ThreadFactory可以很方便的用来创建线程:

public class ThreadFactoryUsage implements ThreadFactory {
private int threadId;
private String name; public ThreadFactoryUsage(String name) {
threadId = 1;
this.name = name;
} @Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name + "-Thread_" + threadId);
log.info("created new thread with id : " + threadId +
" and name : " + t.getName());
threadId++;
return t;
}
}

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/concurrent-overview

更多教程请参考 flydean的博客

java.util.concurrent简介的更多相关文章

  1. java.util.concurrent包详细分析--转

    原文地址:http://blog.csdn.net/windsunmoon/article/details/36903901 概述 Java.util.concurrent 包含许多线程安全.测试良好 ...

  2. Java 理论与实践: 流行的原子——新原子类是 java.util.concurrent 的隐藏精华(转载)

    简介: 在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待.无锁定的算法.在 java.util.concurrent 中添加原子变量类之后,这种情况发生了变化.请跟随并 ...

  3. java.util.concurrent包API学习笔记

    newFixedThreadPool 创建一个固定大小的线程池. shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭. awaitTermination():用于等待子线程结束, ...

  4. java.util.concurrent.Exchanger应用范例与原理浅析--转载

    一.简介   Exchanger是自jdk1.5起开始提供的工具套件,一般用于两个工作线程之间交换数据.在本文中我将采取由浅入深的方式来介绍分析这个工具类.首先我们来看看官方的api文档中的叙述: A ...

  5. 《The java.util.concurrent Synchronizer Framework》 JUC同步器框架(AQS框架)原文翻译

    一.论文简介 闲来无事,看看源码,发现了一篇JDK作者的论文<The java.util.concurrent Synchronizer Framework>主要描述了作者对Abstrac ...

  6. 并发之java.util.concurrent.atomic原子操作类包

    15.JDK1.8的Java.util.concurrent.atomic包小结 14.Java中Atomic包的原理和分析 13.java.util.concurrent.atomic原子操作类包 ...

  7. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  8. Java源码之 java.util.concurrent 学习笔记01

    准备花点时间看看 java.util.concurrent这个包的源代码,来提高自己对Java的认识,努力~~~ 参阅了@梧留柒的博客!边看源码,边通过前辈的博客学习! 包下的代码结构分类: 1.ja ...

  9. jdk8中java.util.concurrent包分析

    并发框架分类 1. Executor相关类 Interfaces. Executor is a simple standardized interface for defining custom th ...

随机推荐

  1. My背包九讲——01背包

    文章目录 背包问题中的常用变量说明 题目 解题思路 我想要想理解最简单 01背包就是要`理解

  2. PTA数据结构与算法题目集(中文) 7-40奥运排行榜 (25 分)

    PTA数据结构与算法题目集(中文)  7-40奥运排行榜 (25 分) 7-40 奥运排行榜 (25 分)   每年奥运会各大媒体都会公布一个排行榜,但是细心的读者发现,不同国家的排行榜略有不同.比如 ...

  3. ASP.NET Core技术研究-探秘依赖注入框架

    ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...

  4. Springboot系列(四)web静态资源配置详解

    Springboot系列(四)web静态资源配置 往期精彩 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 SpringBoot系列(三)配 ...

  5. mpvue的toast弹窗组件-mptosat

    几乎每个小程序都会用到的弹窗功能,弹窗是为了友好的提示用户目前小程序的状态.这样以来toast弹窗就成了小程序不可或缺的组件.mptosat用过,不赖的一款.下面记录以下使用方法: 介绍 mptoas ...

  6. go语言goroutine

    Go语言goroutine 在别的语言里想要在一个程序中实现多任务,如python,python实现多任务可以使用多进程.多线程.携程.但多进程占用资源,多线程无法发挥多核的优势(GIL),pytho ...

  7. 萌新带你开车上p站(二)

    本文作者:萌新 前情提要:萌新带你开车上p站(一) 0x04flag  看题目描述似乎是一个和脱壳相关的逆向题目 按照给出的地址先下载过来 file看看 是个可执行文件 执行之 emm什么都看不出来, ...

  8. 34.3 转换流 InputStreamReader OutStreamReader

    转换流: 把字节输出流转换成字符输出流 标准输入输出流:传输的对象是字节流 System.in . System.out 标准输入输出流 public static final InputStream ...

  9. "六号标题"组件:<h6> —— 快应用组件库H-UI

     <import name="h6" src="../Common/ui/h-ui/text/c_h6"></import> < ...

  10. python3(二十六)slots

    """ """ __author__ = 'shaozhiqi' # python是动态语言,所以定义类后,我们可以动态的给类绑定属性和方法 ...