并发编程与高并发解决方案学习(J.U.C之AQS-CountDownLatch、Semaphore)
AQS同步组件(CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock、Condition、FutureTask)
CountDownLatch(作用类似于join()) 同步辅助类,可以实现阻塞的作用,同一时间只能有一个线程操作该计数器,调用该类的await类会一直处于阻塞状态,直到其他线程调用countDown方法,使当前计数器的值为0(计数器不可以重置)
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Slf4j public class CountDownLatchExample1 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { test(threadNum); } catch (Exception e) { log.error("exception", e); } finally { countDownLatch.countDown(); } }); } countDownLatch.await(); log.info("finish"); exec.shutdown(); } private static void test(int threadNum) throws Exception { Thread.sleep(100); log.info("{}", threadNum); Thread.sleep(100); } }
输出结果
15:54:06.904 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 0 15:54:06.904 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 7 15:54:06.905 [pool-1-thread-19] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 18 15:54:06.904 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 5 15:54:06.904 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 6 15:54:06.904 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 3 15:54:06.904 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 4 15:54:06.904 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 2 15:54:06.904 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 1 15:54:06.904 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 8 15:54:06.905 [pool-1-thread-18] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 17 15:54:06.904 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 9 15:54:06.905 [pool-1-thread-17] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 16 15:54:06.904 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 10 15:54:06.905 [pool-1-thread-20] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 19 15:54:06.905 [pool-1-thread-16] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 15 15:54:06.905 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 12 15:54:06.904 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 11 15:54:06.905 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 14 15:54:06.905 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - 13 15:54:07.009 [main] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample1 - finish
案例2(起了很多线程去完成任务,但是这个任务指向给指定的时间,操作这个时间没做完,也不管了)
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @Slf4j public class CountDownLatchExample2 { private final static int threadCount = 200; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { test(threadNum); } catch (Exception e) { log.error("exception", e); } finally { countDownLatch.countDown(); } }); } countDownLatch.await(10, TimeUnit.MILLISECONDS); log.info("finish"); exec.shutdown(); } private static void test(int threadNum) throws Exception { Thread.sleep(1000); log.info("{}", threadNum); } }输出结果
15:57:13.433 [main] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - finish 15:57:14.423 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 0 15:57:14.435 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 3 15:57:14.436 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 2 15:57:14.436 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 1 15:57:14.438 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 4 15:57:14.441 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 7 15:57:14.442 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 6 15:57:14.442 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 5 15:57:14.442 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 10 15:57:14.443 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 9 15:57:14.443 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 8 15:57:14.443 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 12 15:57:14.443 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 11 15:57:14.443 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 14 15:57:14.444 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 13 15:57:14.444 [pool-1-thread-20] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 19 15:57:14.444 [pool-1-thread-19] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 18 15:57:14.447 [pool-1-thread-18] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 17 15:57:14.447 [pool-1-thread-16] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 15 15:57:14.447 [pool-1-thread-17] INFO com.mmall.concurrency.example.aqs.CountDownLatchExample2 - 16调用shutdown并不是第一时间将线程都全部销毁掉,而是让当前已有的线程全部执行完,之后再把这个线程池销毁掉。Semaphore 信号量(控制并发访问的线程个数,类似于有限的链表,常用语仅能提供有限个访问的资源,比如 控制数据库连接数)
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; @Slf4j public class SemaphoreExample1 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { semaphore.acquire(); // 每次获取一个许可 test(threadNum); semaphore.release(); // 每次释放一个许可 } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
输出结果(一次3条输出)
15:59:19.291 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 1 15:59:19.291 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 0 15:59:19.291 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 2 15:59:20.309 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 3 15:59:20.310 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 4 15:59:20.310 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 5 15:59:21.310 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 6 15:59:21.310 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 7 15:59:21.311 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 8 15:59:22.310 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 9 15:59:22.310 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 10 15:59:22.311 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 11 15:59:23.311 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 12 15:59:23.311 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 13 15:59:23.312 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 14 15:59:24.311 [pool-1-thread-16] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 15 15:59:24.311 [pool-1-thread-17] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 16 15:59:24.312 [pool-1-thread-18] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 17 15:59:25.312 [pool-1-thread-20] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 19 15:59:25.312 [pool-1-thread-19] INFO com.mmall.concurrency.example.aqs.SemaphoreExample1 - 18
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; @Slf4j public class SemaphoreExample2 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { semaphore.acquire(3); // 每次获取多个许可 test(threadNum); semaphore.release(3); // 每次释放多个许可 } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
输出结果(一次一条输出)
16:00:37.474 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 0 16:00:38.480 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 1 16:00:39.480 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 2 16:00:40.481 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 3 16:00:41.482 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 4 16:00:42.482 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 5 16:00:43.483 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 6 16:00:44.483 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 7 16:00:45.484 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 8 16:00:46.484 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 9 16:00:47.484 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 10 16:00:48.485 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 11 16:00:49.485 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 12 16:00:50.485 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 13 16:00:51.486 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 14 16:00:52.486 [pool-1-thread-17] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 16 16:00:53.486 [pool-1-thread-16] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 15 16:00:54.486 [pool-1-thread-18] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 17 16:00:55.487 [pool-1-thread-19] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 18 16:00:56.488 [pool-1-thread-20] INFO com.mmall.concurrency.example.aqs.SemaphoreExample2 - 19
案例(假如当前并发数是3,超过3个就丢弃)
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @Slf4j public class SemaphoreExample3 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { if (semaphore.tryAcquire()) { // 尝试获取一个许可 test(threadNum); semaphore.release(); // 释放一个许可 } } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
输出结果
16:01:45.406 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.SemaphoreExample3 - 1 16:01:45.405 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.SemaphoreExample3 - 0 16:01:45.413 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.SemaphoreExample3 - 2尝试获得许可,只让执行5秒
import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @Slf4j public class SemaphoreExample4 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { if (semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS)) { // 尝试获取一个许可 test(threadNum); semaphore.release(); // 释放一个许可 } } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
输出结果(一次三条输出)
16:02:31.454 [pool-1-thread-3] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 2 16:02:31.454 [pool-1-thread-1] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 0 16:02:31.454 [pool-1-thread-2] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 1 16:02:32.463 [pool-1-thread-4] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 3 16:02:32.464 [pool-1-thread-5] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 4 16:02:32.464 [pool-1-thread-6] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 5 16:02:33.464 [pool-1-thread-8] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 7 16:02:33.464 [pool-1-thread-7] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 6 16:02:33.465 [pool-1-thread-9] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 8 16:02:34.465 [pool-1-thread-10] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 9 16:02:34.465 [pool-1-thread-11] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 10 16:02:34.466 [pool-1-thread-12] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 11 16:02:35.465 [pool-1-thread-13] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 12 16:02:35.466 [pool-1-thread-14] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 13 16:02:35.466 [pool-1-thread-15] INFO com.mmall.concurrency.example.aqs.SemaphoreExample4 - 14
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。