ReadWriteLock使用详解

前面讲到的ReentrantLock保证了只有一个线程可以执行临界区代码: public class Counter { private final Lock lock = new ReentrantLock(); private int counts = new int; public void inc(int index) { lock.lock(); try { counts
ReadWriteLock使用详解

乐观锁StampedLock实现同时读写操作

前面介绍的ReadWriteLock可以解决多线程同时读,但只有一个线程能写的问题。 如果我们深入分析ReadWriteLock,会发现它有个潜在的问题:如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,即读的过程中不允许写,这是一种悲观的读锁。 要进一步提升并发执行效率,Java 8引入了新的读写锁:StampedLock。 StampedLock和ReadWriteLock相比,改进
乐观锁StampedLock实现同时读写操作

信号计数器Semaphore访问受限资源

前面我们讲了各种锁的实现,本质上锁的目的是保护一种受限资源,保证同一时刻只有一个线程能访问(ReentrantLock),或者只有一个线程能写入(ReadWriteLock)。 还有一种受限资源,它需要保证同一时刻最多有N个线程能访问,比如同一时刻最多创建100个数据库连接,最多允许10个用户下载等。 这种限制数量的锁,如果用Lock数组来实现,就太麻烦了。 这种情况就可以使用Semaphore,
信号计数器Semaphore访问受限资源

并发工具Concurrent详解

我们在前面已经通过ReentrantLock和Condition实现了一个BlockingQueue: public class TaskQueue { private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private Queue<St
并发工具Concurrent详解

Atomic原子操作实现线程安全

Java的java.util.concurrent包除了提供底层锁、并发集合外,还提供了一组原子操作的封装类,它们位于java.util.concurrent.atomic包。 我们以AtomicInteger为例,它提供的主要操作有: 增加值并返回新值:int addAndGet(int delta) 加1后返回新值:int incrementAndGet() 获取当前值:int get() 用
Atomic原子操作实现线程安全

Java线程池详解

Java语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。 如果可以复用一组线程: ┌─────┐ execute ┌──────────────────┐ │Task1│─────────▶│ThreadPool │ ├─────┤ │┌───────┐┌───────┐│ │Task2│ ││Thre
Java线程池详解

使用Future获取异步执行结果

在执行多个任务的时候,使用Java标准库提供的线程池是非常方便的。我们提交的任务只需要实现Runnable接口,就可以让线程池去执行: class Task implements Runnable { public String result; public void run() { this.result = longTimeCalculation(); } } Runnable接口有个问题,它
使用Future获取异步执行结果

CompletableFuture异步处理多线程结果详解

使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。 从Java 8开始引入了CompletableFuture,它针对Future做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。 我们以获取股票价格为例,看看如何使用CompletableFuture: //
CompletableFuture异步处理多线程结果详解