个人随笔
目录
并发(六)、Java并发工具类的简单使用
2021-04-26 17:00:03

Java为我们提供了一些效果非常不错的并发工具类,这里主要介绍一下如下几个工具类的使用,并不会去深究实现原理(其实原理都是通过自旋CAS,CAS对应的处理器原子操作指令是CMPXCHG)。

Semaphore
CountDownLatch
CyclicBarrier
Executors

一、Semaphore

1、作用

设定信号量,只有获得信号量的线程才能够往后执行业务逻辑,没有获得信号量的线程只能阻塞等待唤醒重新尝试获得信号量,可用于服务限流。

2、代码示例

  1. /**
  2. * Semaphore作用:设定信号量,只有获得信号量的线程才能够往后执行业务逻辑,
  3. * 没有获得信号量的线程只能阻塞等待唤醒重新尝试获得信号量,可用于服务限流
  4. * @author 爱吃鱼的乌贼
  5. */
  6. public class SemaphoreTest {
  7. public static void main(String[] args) {
  8. //设定信号量,只允许2个线程同时处理
  9. Semaphore semaphore = new Semaphore(2);
  10. for(int i=0;i<10;i++) {
  11. new Thread(new Runnable() {
  12. public void run() {
  13. try {
  14. //获取信号量
  15. semaphore.acquire();
  16. System.out.println("Thread:"+Thread.currentThread().getId()+"获得信号量"+new Date());
  17. Thread.sleep(5000);
  18. System.out.println("Thread:"+Thread.currentThread().getId()+"释放信号量"+new Date());
  19. semaphore.release();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }).start();
  25. }
  26. }
  27. }

二、CountDownLatch

1、作用

能够使一个线程等待其他线程完成各自的工作后再执行

2、代码示例

  1. /**
  2. * CountDownLatch 能够使一个线程等待其他线程完成各自的工作后再执行
  3. * @author 爱吃鱼的乌贼
  4. */
  5. public class CountDownLatchTest {
  6. public static void main(String[] args) throws InterruptedException {
  7. CountDownLatch countDownLatch = new CountDownLatch(2);
  8. new Task1(countDownLatch).start();
  9. new Task2(countDownLatch).start();
  10. countDownLatch.await();
  11. System.out.println("起锅烧油");
  12. }
  13. public static class Task1 extends Thread{
  14. CountDownLatch countDownLatch;
  15. public Task1(CountDownLatch countDownLatch) {
  16. this.countDownLatch = countDownLatch;
  17. }
  18. @Override
  19. public void run() {
  20. System.out.println("正在洗菜中....");
  21. try {
  22. Thread.sleep(5000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. System.out.println("菜已洗好!");
  27. countDownLatch.countDown();
  28. }
  29. }
  30. public static class Task2 extends Thread{
  31. CountDownLatch countDownLatch;
  32. public Task2(CountDownLatch countDownLatch) {
  33. this.countDownLatch = countDownLatch;
  34. }
  35. @Override
  36. public void run() {
  37. System.out.println("正在煮饭中....");
  38. try {
  39. Thread.sleep(6000);
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. System.out.println("饭已煮好!");
  44. countDownLatch.countDown();
  45. }
  46. }
  47. }

三、CyclicBarrier

1、作用

栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。

2、代码示例

  1. /**
  2. * CyclicBarrier 栅栏屏障,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,
  3. * 直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
  4. * @author 爱吃鱼的乌贼
  5. */
  6. public class CyclicBarrierTest {
  7. public static void main(String[] args) {
  8. CyclicBarrier cyclicBarrier =new CyclicBarrier(10);
  9. for(int i=0;i<10;i++) {
  10. new Thread(new Runnable() {
  11. public void run() {
  12. try {
  13. Thread.sleep(new Random().nextInt(1000)+1000);
  14. System.out.println("Thread:"+Thread.currentThread().getId()+"已经准备好");
  15. cyclicBarrier.await();
  16. System.out.println("Thread:"+Thread.currentThread().getId()+"开始出发");
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }).start();
  22. }
  23. }
  24. }

四、Executors

1、作用

主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单

  • newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO, 优先级)执行。

2、代码示例

  1. /**
  2. * Executors:主要用来创建线程池,代理了线程池的创建,使得你的创建入口参数变得简单
  3. * @author 爱吃鱼的乌贼
  4. */
  5. public class ExecutorsTest {
  6. public static void main(String[] args) {
  7. // 1、newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  8. ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
  9. for (int i = 0; i < 10; i++) {
  10. cachedThreadPool.execute(new Runnable() {
  11. @Override
  12. public void run() {
  13. // 这里会发现结果有重复的线程ID
  14. System.out.println("Thread:" + Thread.currentThread().getId() + ";newCachedThreadPool");
  15. }
  16. });
  17. }
  18. // 2、newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  19. ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
  20. for (int i = 0; i < 10; i++) {
  21. newFixedThreadPool.execute(new Runnable() {
  22. @Override
  23. public void run() {
  24. try {
  25. Thread.sleep(2000);
  26. } catch (InterruptedException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. }
  30. // 这里会发现两个两个执行完后才继续执行,并且线程ID不变
  31. System.out.println("Thread:" + Thread.currentThread().getId() + ";newFixedThreadPool");
  32. }
  33. });
  34. }
  35. // 3、newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
  36. ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);
  37. // 延迟3秒钟后执行任务
  38. newScheduledThreadPool.schedule(new Runnable() {
  39. @Override
  40. public void run() {
  41. System.out.println("运行时间: " + new Date());
  42. }
  43. }, 3, TimeUnit.SECONDS);
  44. // 延迟1秒钟后每隔3秒执行一次任务
  45. newScheduledThreadPool.scheduleAtFixedRate(new Runnable() {
  46. @Override
  47. public void run() {
  48. System.out.println("运行时间: " + new Date());
  49. }
  50. }, 1, 3, TimeUnit.SECONDS);
  51. // 4、newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
  52. ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
  53. for (int i = 0; i < 10; i++) {
  54. newSingleThreadExecutor.execute(new Runnable() {
  55. @Override
  56. public void run() {
  57. // 这里会发现结果有重复的线程ID
  58. System.out.println("Thread:" + Thread.currentThread().getId() + ";newSingleThreadExecutor");
  59. }
  60. });
  61. }
  62. }
  63. }
 245

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2