基于AQS实现的工具类

seamphore 和countDownlatch ReentLock都是基于AQS 用于线程间通信的工具。

CyclicBarrier:线程屏障. 和countDownLatch基本上差不多功能,不同地方就是CycliBarrier可以多次使用

seamphore:信号量,作用就是控制访问指定资源线程数目,底层依赖于AQS状态的status. 可以做限流 在微服务里面Hystix有两种限流方式 应该是基于线程池 另外一个就是基于信号量做的.

使用场景:在调用另外一个服务的时候可以加一个seamphore(3000) 也就是说最大支持过来的线程有3000个可以拿到信号量,拿不到信号量的线程全部都阻塞在外面。

Semaphore semaphore = new Semaphore(20);
//20相当于一开始参加两个票据
semaphore.acquire(2);//获取公共资源  从上面20给票据里面拿2个票据如果没有2个了会等这个方法支持中断
semaphore.release(); //将票据还回去

//也可以使用
if(seamphore.tryAcquire(500,....)) // 表示最多等500ms  如果还没有拿到票据注解降级
{
    
}else{
    //降级的逻辑.........
}
Hsytil就是使用的这样的逻辑

CountDownLaunch:可以理解为计数器, 就是调用countDownLatch.await()会等待使用的线程都到达这个地方才会执行下面的逻辑 但是只能用一次

CountDownLatch countDownLatch = new CountDownLatch(10);
//new Threadxxxxxx逻辑1
//new Threadxxxxxx逻辑2
countDownLatch.await();  //这里就表示当所有的的线程都执行完逻辑1和逻辑2  才会去执行countDownLatch.await()方法后面的逻辑.

public static void main(String[] args) throws InterruptedException {
    long now = System.currentTimeMillis();
    CountDownLatch countDownLatch = new CountDownLatch(1);

    /*new Thread(new SeeDoctorTask(countDownLatch)).start();
    new Thread(new QueueTask(countDownLatch)).start();*/


    for(int i=0;i<10;i++){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    countDownLatch.await();  //表示等到上面所有的线程都启动完成了才继续下面的逻辑 (相当于等所有的线程引擎执行下面的逻辑)    可以模拟线程的并行度
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (object){
                    for(int j=0;j<1000;j++){
                        sub++;
                    }
                }

            }
        });
    }
    Thread.sleep(3000);
    //等待线程池中的2个任务执行完毕,否则一直等待,zk分布式锁   
    countDownLatch.countDown();  
    System.out.println("over,回家 cost:"+(System.currentTimeMillis()-now));
}

Atomic: 原子类的工具包.比如AtomicInreger AtomicBoolean等等......

使用就是参加1000个线程 堆count++ 用AtomicInteger可以直接保证原子行的操作,而不需要加synchronized. 底层是基于CAS的一种无锁的算法

CAS:比较与交换 底层就是基于unsafe类的api---> CASObject CASIntenge CASLong方法 最底层还是依赖硬件CMPXCHG去实现.

大概的逻辑: 就是先读取一份到数据到自己的工作内存里面去, 再去执行自己的业务逻辑去修改值,最后在拿自己工作内存里面的数据和主内存里面的数据进行比较(看看期间有没有线程堆主内存里面的数据进行修改) 如果保持一直就可以将修改后的值写回主内存里面,否则就丢弃.

要用CAS修改对象属性的值,就要做到该属性在对象内存空间里面的位置(也就是偏移量)

总结: Atomic底层是基于CAS实现的, CAS底层又是基于Unsafe类api实现的, Unsafe又是依赖于硬件实现.

ABA问题: 就是CAS原子比较与交换的bug.就是相当于比如说第一次出现数据为A 最后查询的数据也为A 但是中间有一个B的数据. A变成B B又变成A的过程没有看到.(假如有两个线程堆数据进行操作,T1查询数据为1 刚好T2将数据操作为2,此时T1的逻辑没有执行完成 T2快速又将数据改回1,此时T1再去查询数据还是1)

解决ABA问题:有一个版本号,数据变化一次版本号就+1 虽然最后数据一致,还会去比较版本号如果版本号不一致数据肯定被改过. AtomicStampeRefencce这个类可以做到

Unsafe魔法类: 堆外内存(虚拟机外面的空间)一般可以使用Unsafe这个类进行申请管理. 这个类里面有很多的native的方法. 在jdk1.7后提供了一些不安全的api可以绕过jvm内存管理直接可以操作内存系统资源.自主的去管理系统内存.. 就是可以理解Unsafe提供了一个后门直接可以操作系统资源.

有一个情况,假如对于文件上传,假如这个接口被很多的请求访问,就可以看到jvm使用率会非常的高, 就可以使用Unsafe申请堆外内存,业务堆外内存不属于GC管,使用用完一定要手动释放(否则会导致内存泄漏).

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值