Memorydoc
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
    • HTML
    • CSS
    • 前端拓展
  • 编程之道

    • 并发编程
    • 设计模式
    • 数据结构算法
    • 技术拓展
    • 技术陷阱
    • 面试宝典
  • 分布式

    • 微服务
    • 数据库
  • 项目优化实战

    • JVM 优化
    • 线程池优化
    • 模板引擎优化
    • 任务调度优化
    • 内存优化
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Memorydoc

术尚可求
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
    • HTML
    • CSS
    • 前端拓展
  • 编程之道

    • 并发编程
    • 设计模式
    • 数据结构算法
    • 技术拓展
    • 技术陷阱
    • 面试宝典
  • 分布式

    • 微服务
    • 数据库
  • 项目优化实战

    • JVM 优化
    • 线程池优化
    • 模板引擎优化
    • 任务调度优化
    • 内存优化
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 并发编程

    • 多线程基础
    • Atomic
    • synchronized
    • volatile(内存可见)
    • ReentrantLock
    • Lock 和 CountDownLatch
    • 线程池
    • 并发集合
    • 综合
    • 线程约束
      • 控制线程并发数量
      • 线程执行屏障
    • 线程通信
    • 情景案例
    • AQS(AbstractQueuedSynchronizer)
    • 自己实现锁
    • 通过lock 手写阻塞队列
    • 通过Condition 手写阻塞队列
    • 阻塞队列实现生产者消费者模式
    • StampedLock 乐观读写锁
  • 设计模式

  • 数据结构算法

  • 技术拓展

  • 技术陷阱

  • 面试宝典

  • 微服务

  • 数据库

  • 项目优化背景

  • JVM优化

  • 技术架构
  • 并发编程
Memorydoc
2022-03-07

线程约束原创

# 控制线程并发数量

1.该类可以控制线程并发数量,相当于给线程颁发执行许可证

public class SemaphoreTest1 {
    private Semaphore semaphore = new Semaphore(1);//表示只能有一个线程可以执行acquire() 和release()之间的代码

    public class Service{
        public void testMethod(){
            try{
                semaphore.acquire();
                System.out.println( Thread.currentThread().getName());
                System.out.println(semaphore.hasQueuedThreads());
            }catch (Exception ex){
                semaphore.release();
            }
        }

    }

    public static void main(String[] args) {

    }
   //semaphore.acquireUninterruptibly() 该方法不允许进入accquire的线程被打断(interrupt)
   //semaphore.availablePermits() 返回Semaphore中当前正在使用的许可证数量
   //semaphore.drainPermits() 返回当前可用的许可证数量
   //semaphore.hasQueuedThreads() 返回是否线程在等待当前许可证
   //semaphore.getQueueLength() 返回等待许可证的线程个数

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

2.可以起到减缓压力的作用(和ReentrantLock同时使用)

    /**
     * 这里所说的同步代码段是 acquire 和release之前的代码段,可以起到减缓压力的作用
     */
        //可以将 Semaphore 和ReentrantLock同时使用,这样就可以实现控制制定线程数量执行代码块,同时,保证了同步执行
        //本例中代码块中一次只能进入三个线程,并且三个线程是串行处理,保证了线程安全,防止高QPS压力,将压力减缓
    public class SemaphoreTest2 {
        private boolean isFail = false;
        private Semaphore semaphore = new Semaphore(3, isFail);//可以将同步代码段变成非公平锁,这样就不会局限于线程执行顺序
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();//可以控制被lock锁住的代码块 等待 condition.await() 或者 唤醒 condition.signalAll()
        public void testMethod() {
            try {
                //semaphore.tryAcquire();//尝试获取一个许可证,默认是一个,如果获得成功返回true
                //semaphore.tryAcquire(3);//尝试获得三个许可证,获得成功返回true;
                //semaphore.tryAcquire(2, TimeUnit.SECONDS);//尝试在两秒钟获取2个执行许可证,如果获得返回true
    
                semaphore.acquire();
                lock.lock();
                System.out.println("ThreadName=" + Thread.currentThread().getName());
            } catch (Exception ex) {
            } finally {
                lock.unlock();
                semaphore.release();
            }
        }
    }
    
    122112sdsddssdsads
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 线程执行屏障

CyclicBarrier 线程执行屏障,约定线程个数,如果到达cyclicBarrier.await();的线程数不够约定的线程个数,则等待

public class Test {
    public static void main(String[] args) {
        //约定2个线程 到达屏障
        // 如果到达的线程数量没有2个,那么不会执行,构造器第二个参数的方法
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                System.out.println("全来了");
            }
        });
        for (int i =0; i< 4; i++){
            ThreadA threadA = new ThreadA(cyclicBarrier);
            //cyclicBarrier.getNumberWaiting() 获取几个线程已经到达了屏障点
            //获取parties的个数
            threadA.start();
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static class ThreadA  extends  Thread{
        private CyclicBarrier cyclicBarrier;
        public ThreadA(CyclicBarrier cyclicBarrier) {
            super();
            this.cyclicBarrier= cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "开始=" + System.currentTimeMillis() + "等待凑齐2个线程开始执行");
            try {
                cyclicBarrier.await();
                System.out.println(Thread.currentThread().getName() + "结束=" + System.currentTimeMillis() + "已经凑齐2个线程开始执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
编辑 (opens new window)
上次更新: 2022/03/13, 21:24:24
综合
线程通信

← 综合 线程通信→

最近更新
01
命令模式 原创
05-03
02
桥接模式 原创
05-02
03
优雅写代码三 原创
04-29
更多文章>
Theme by Memorydoc | Copyright © 2021-2022 Memorydoc | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式