龙空技术网

【JDK并发包基础】工具类详解

大墨小汐 268

前言:

此刻朋友们对“nginxlua防刷”大致比较关注,各位老铁们都需要知道一些“nginxlua防刷”的相关内容。那么小编同时在网络上网罗了一些有关“nginxlua防刷””的相关资讯,希望看官们能喜欢,朋友们一起来了解一下吧!

在写并发代码来提升性能时,会遵循某些最佳写法,而不是只用基础的wait和notify来控制复杂的流程。Java.util.concurrent 包是专为 Java并发编程而设计的包,它下有很多编写好的工具,使用这些更高等的同步工具来编写代码,让我们的程序可以不费力气就得到优化。这些工具还在由一些优秀的工程师不断优化和完善,我们不必重复造轮子:

脑图地址,感谢深入浅出 Java Concurrency ,此脑图在这篇基础上修改而来。其中我们先看工具类部分:

1.ReentrantLock

2.Condition

3.Semaphore

4.ReentrantReadWriteLock

5.CountDownLatch

6.CyclicBarrrer

1.ReentrantLock

1.1可重入

单线程可以重复进入,但必须重复退出。

一个线程拿到几个许可,就得释放几次,不然就造成线程等待,可在命令行查看等待的线程:jps -->jstack [ option ] pid

1.2可中断

长期线程在锁上等待问题,可以通过中断来解决:

可在命令行查看死锁:jps -->jstack [ option ] pid

1.3可限时

可限时也是一个避免永久等待构成死锁的解决方法:

p

1.4公平锁

先来的线程先得到锁。如果先来的线程一直拿不到锁,则会产生饥饿现象,公平锁虽然不会产生饥饿现象,因为产生排队问题,会导致程序效率差。通过阅读ReentrantLock的源码发现:默认是非公平的,如果传入true,则是公平锁:

2.Condition

Condition与ReentrantLock的关系就类似于synchronized与Object.wait()/notify()。但是它与ReentrantLock结合使用,有await和signal与之对应.

利用Condition实现顺序执行:

3.Semaphore

翻译为信号量,允许多个线程进入临界区。说白了就是一个广义上的锁,相当于共享锁。比如信号量中我可以给它指定10个许可,每一个许可可以分配给若干个线程(当然一个线程也可以拿多个许可),拿到许可线程可以执行,如果许可分发完了,后面的线程就和锁一样去做等待。换句话说,当信号量等于1的时候,就相当于一把锁。

比如早期做限流时,我们系统是8核cpu,设置同时请求任务为8个,超过8个,可以用信号量让线程等待来加以控制:

一般限流java用的不多,实际中一种思路是用redis,存用户的session到redis中,统计一分钟之内访问url的次数count,如果count大于额定次数,则是恶意攻击。redis里有个expried,每过60秒,把index清零,然后重新统计。现在互联网公司成熟的限流方案是使用:nginx + lua + redis 防刷和限流。

4.ReentrantReadWriteLock

ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限, 它和后者都是单独的实现,彼此之间没有继承或实现的关系。读写锁可以很好的提高程序效率,如果读也加锁的话,每次只有一个线程能访问,不符合高并发程序设计。ReentrantLock和synchronized都属于阻塞的并行,会把线程挂起,而ReadWriteLock属于无等待的并发。

访问情况:读读共享,读写互斥,写写互斥

5.CountDownLatch

实际开发中经常用于监听某些初始化操作,等待初始化完成后,通知主线程继续工作,它相当于一个栅栏

6.CyclicBarrrer

倒数计时器。假设有一个场景:每个线程代表一个跑步运动员,当运动员都准备好后,才能一起出发,只要有一个人没有准备好,大家都等待:

最后,我们解决高并发可以从以下几个方面入手:1.Nginx网络带宽硬件方面等。2.业务细粒度化。3.限流。4.集群。5.异步。6.缓存。其中最主要的还是业务细粒度化。

标签: #nginxlua防刷