1.重入锁(ReentrantLock)
重入锁使用java.util.concurrent.locks.ReentrantLock类来实现,具有与synchronized关键字相似的功能。
1 package com.company;
2
3 import java.util.concurrent.locks.ReentrantLock;
4
5 public class User implements Runnable {
6 private ReentrantLock lock = new ReentrantLock();
7 static int i = 0;
8 @Override
9 public void run() {
10 lock.lock();
11 for (int j = 0; j < 10000000; j++) {
12 i++;
13 }
14 System.out.println(i);
15 lock.unlock();
16 }
17
18 public static void main(String[] args) throws InterruptedException {
19 //注意要使用同一个对象创建线程
20 User u = new User();
21 Thread t1 = new Thread(u);
22 Thread t2 = new Thread(u);
23 t1.start();
24 t2.start();
25 }
26 }
- 锁的时候响应中断
1 package com.company;
2
3 import java.util.concurrent.locks.ReentrantLock;
4
5 public class User implements Runnable {
6 private ReentrantLock lock1 = new ReentrantLock();
7 private ReentrantLock lock2 = new ReentrantLock();
8
9 @Override
10 public void run() {
11 //线程t1先持有lock1,休眠0.5秒尝试持有lock2
12 if(Thread.currentThread().getName().equals("t1")){
13 try {
14 lock1.lockInterruptibly();
15 Thread.sleep(500);
16 lock2.lockInterruptibly();
17 } catch (InterruptedException e) {
18 e.printStackTrace();
19 }
20 //线程t2先持有lock2,休眠0.5秒尝试持有lock1,但是lock1在被t1持有,导致死锁
21 //主线程休眠5秒后,中断线程t1,t1被中断,t2继续执行,执行完毕后退出。
22 }else{
23 try {
24 lock2.lockInterruptibly();
25 Thread.sleep(500);
26 lock1.lockInterruptibly();
27 } catch (InterruptedException e) {
28 e.printStackTrace();
29 }
30 }
31 if(lock1.isHeldByCurrentThread()){
32 lock1.unlock();
33 }
34 if(lock2.isHeldByCurrentThread()){
35 lock2.unlock();
36 }
37 }
38
39 public static void main(String[] args) throws InterruptedException {
40 //注意要使用同一个对象创建线程
41 User u = new User();
42 Thread t1 = new Thread(u,"t1");
43 Thread t2 = new Thread(u,"t2");
44 t1.start();
45 t2.start();
46 Thread.sleep(5000);
47 t1.interrupt();
48 }
49 }
- 设定锁的等待时间
1 package com.company;
2
3 import org.omg.PortableServer.THREAD_POLICY_ID;
4
5 import java.util.concurrent.TimeUnit;
6 import java.util.concurrent.locks.ReentrantLock;
7
8 public class User implements Runnable {
9 private ReentrantLock lock = new ReentrantLock();
10
11 @Override
12 public void run() {
13 try {
14 if(lock.tryLock(5, TimeUnit.SECONDS)){
15 System.out.println(Thread.currentThread().getName()+"成功获得锁");
16 Thread.sleep(6000);
17 }else{
18 System.out.println(Thread.currentThread().getName()+"获得锁失败");
19 }
20 } catch (InterruptedException e) {
21 e.printStackTrace();
22 }
23 }
24
25 public static void main(String[] args) throws InterruptedException {
26 //注意要使用同一个对象创建线程
27 User u = new User();
28 Thread t1 = new Thread(u,"t1");
29 Thread t2 = new Thread(u,"t2");
30 t1.start();
31 t2.start();
32 }
33 }
- 设定线程公平获得锁
公平锁需要维护有序队列,成本高。
1 package com.company;
2
3 import org.omg.PortableServer.THREAD_POLICY_ID;
4
5 import java.util.concurrent.TimeUnit;
6 import java.util.concurrent.locks.ReentrantLock;
7
8 public class User implements Runnable {
9 //还有一个带有boolean参数的构造方法,为true时多个线程公平的获得锁
10 private ReentrantLock lock = new ReentrantLock(true);
11
12 @Override
13 public void run() {
14 while(true){
15 lock.lock();
16 try {
17 System.out.println(Thread.currentThread().getName()+"获得锁");
18 Thread.sleep(100);
19 } catch (InterruptedException e) {
20 e.printStackTrace();
21 }
22 lock.unlock();
23 }
24 }
25
26 public static void main(String[] args) throws InterruptedException {
27 //注意要使用同一个对象创建线程
28 User u = new User();
29 Thread t1 = new Thread(u,"t1");
30 Thread t2 = new Thread(u,"t2");
31 t1.start();
32 t2.start();
33 }
34 }
- 重入锁的wait和notify
重入锁的等待唤醒使用Condition类,等待使用await()方法,唤醒使用signal()方法,
1 package com.company;
2 import java.util.concurrent.locks.Condition;
3 import java.util.concurrent.locks.ReentrantLock;
4
5 public class User implements Runnable {
6 public static ReentrantLock lock = new ReentrantLock();
7 public static Condition condition = lock.newCondition();
8
9 @Override
10 public void run() {
11 try {
12 lock.lock();
13 condition.await();
14 System.out.println("唤醒了");
15 } catch (InterruptedException e) {
16 e.printStackTrace();
17 }
18 lock.unlock();
19 }
20
21 public static void main(String[] args) throws InterruptedException {
22 //注意要使用同一个对象创建线程
23 User u = new User();
24 Thread t = new Thread(u);
25 t.start();
26 Thread.sleep(1000);
27 //condition只能用在lock块内
28 lock.lock();
29 condition.signal();
30 lock.unlock();
31 }
32 }
2.信号量(Semaphore)
synchronized关键字和重入锁同一时间只支持一个线程进入,信号量允许多个线程进入。
1 package com.company;
2 import java.util.concurrent.ExecutorService;
3 import java.util.concurrent.Executors;
4 import java.util.concurrent.Semaphore;
5
6 public class User implements Runnable {
7 final Semaphore semp = new Semaphore(5);
8
9 @Override
10 public void run() {
11 try {
12 semp.acquire();
13 Thread.sleep(1000);
14 System.out.println(Thread.currentThread().getName()+"执行完了");
15 } catch (InterruptedException e) {
16 e.printStackTrace();
17 }
18 semp.release();
19
20 }
21
22 public static void main(String[] args) throws InterruptedException {
23 //创建一个线程池,池里边有20个线程
24 ExecutorService executorService = Executors.newFixedThreadPool(20);
25 final User user= new User();
26 for (int i = 0; i < 20; i++) {
27 executorService.submit(user);
28 }
29 }
30 }
3.读写锁
读写锁应用于读的次数远大于写的次数的场景,因为2个线程同时读并没有对资源修改,所以可以同时读,但是但凡一个线程有写操作,就会阻塞其他线程

1 package com.company;
2
3
4 import java.util.concurrent.CountDownLatch;
5 import java.util.concurrent.locks.Lock;
6 import java.util.concurrent.locks.ReadWriteLock;
7 import java.util.concurrent.locks.ReentrantLock;
8 import java.util.concurrent.locks.ReentrantReadWriteLock;
9
10 public class Main {
11
12 public void readSth(){
13 try {
14 Thread.sleep(1000);
15 } catch (InterruptedException e) {
16 e.printStackTrace();
17 }
18 }
19
20 public void writeSth(){
21 try {
22 Thread.sleep(2000);
23 } catch (InterruptedException e) {
24 e.printStackTrace();
25 }
26 }
27 //注意reader类和writer类需要持有同一个类的锁,这2个类持有同一个Main对象
28 public static class Reader implements Runnable{
29 private ReadWriteLock readWriteLock;
30 private Lock readlock;
31 private CountDownLatch latch;
32 private Main obj;
33
34 public Reader(ReadWriteLock readWriteLock,CountDownLatch latch,Main obj){
35 this.readWriteLock = readWriteLock;
36 this.readlock = readWriteLock.readLock();
37 this.latch = latch;
38 this.obj = obj;
39 }
40
41
42 @Override
43 public void run() {
44 readlock.lock();
45 obj.readSth();
46 readlock.unlock();
47 latch.countDown();
48 }
49 }
50
51 public static class Writer implements Runnable{
52 private ReadWriteLock readWriteLock;
53 private Lock writelock;
54 private CountDownLatch latch;
55 private Main obj;
56
57 public Writer(ReadWriteLock readWriteLock,CountDownLatch latch,Main obj){
58 this.readWriteLock = readWriteLock;
59 this.writelock = readWriteLock.writeLock();
60 this.latch = latch;
61 this.obj = obj;
62 }
63
64
65 @Override
66 public void run() {
67 writelock.lock();
68 obj.writeSth();
69 writelock.unlock();
70 latch.countDown();
71 }
72 }
73 public static void main(String[] args) throws InterruptedException {
74 final long start = System.currentTimeMillis();
75 ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
76 final CountDownLatch latch = new CountDownLatch(25);
77 Main m = new Main();
78 for (int i = 0; i < 20; i++) {
79 Thread t = new Thread(new Reader(readWriteLock,latch,m));
80 t.start();
81 }
82 for (int i = 0; i < 5; i++) {
83 Thread t = new Thread(new Writer(readWriteLock,latch,m));
84 t.start();
85 }
86 latch.await();
87 final long end = System.currentTimeMillis();
88 final long cost = (end - start) /1000;
89 //执行时间11s
90 System.out.println(cost);
91 }
92 }
4.等待多个线程执行完的CountDownLatch
CountDownLatch可以让一个线程等待多个线程执行完后在执行。
1 package com.company;
2
3 import java.util.concurrent.CountDownLatch;
4
5 public class User implements Runnable {
6 private CountDownLatch c;
7
8 public User(CountDownLatch c){
9 this.c = c;
10 }
11
12 @Override
13 public void run() {
14 try {
15 Thread.sleep(2000);
16 } catch (InterruptedException e) {
17 e.printStackTrace();
18 }
19 c.countDown();
20
21 }
22
23 public static void main(String[] args) throws InterruptedException {
24 long start = System.currentTimeMillis();
25 CountDownLatch c = new CountDownLatch(10);
26 for (int i = 0; i < 10; i++) {
27 new Thread(new User(c)).start();
28 }
29 c.await();
30 long end = System.currentTimeMillis();
31 System.out.println((end-start)/1000+"秒后所有线程都执行完了");
32 }
33 }
5.反复等待多个线程执行完的CyclicBarrier(?)

1 package com.company;
2
3 import java.util.Random;
4 import java.util.concurrent.BrokenBarrierException;
5 import java.util.concurrent.CyclicBarrier;
6
7 public class CyclicBarrierDemo {
8 public static class Solider implements Runnable{
9 private String solider;
10 private final CyclicBarrier cyclic;
11
12 public Solider(String solider,CyclicBarrier cyclic) {
13 this.solider = solider;
14 this.cyclic = cyclic;
15 }
16
17 @Override
18 public void run() {
19 try {
20 //等士兵集合
21 cyclic.await();
22 doWork();
23 //等士兵完成任务
24 cyclic.await();
25 } catch (InterruptedException e) {
26 e.printStackTrace();
27 } catch (BrokenBarrierException e) {
28 e.printStackTrace();
29 }
30 }
31
32 void doWork() throws InterruptedException {
33 Thread.sleep(Math.abs(new Random().nextInt() % 10000));
34 System.out.println(solider+"任务完成");
35 }
36 }
37 //一批线程执行完了,最后执行什么
38 public static class BarrierRun implements Runnable{
39 boolean flag;
40 int N;
41
42 public BarrierRun(boolean flag,int N){
43 this.flag = flag;
44 this.N = N;
45 }
46 @Override
47 public void run() {
48 if(flag){
49 System.out.println("司令:"+N+"个士兵完成任务");
50 }else{
51 System.out.println("司令:"+N+"个士兵集合完毕");
52 flag = true;
53 }
54 }
55 }
56
57 public static void main(String[] args) {
58 final int N = 10;
59 boolean flag = false;
60 CyclicBarrier cyclicBarrier = new CyclicBarrier(N,new BarrierRun(flag,N));
61 System.out.println("集合队伍");
62 for (int i = 0; i < N; i++) {
63 System.out.println("士兵"+i+"报道");
64 new Thread(new Solider("士兵"+i,cyclicBarrier)).start();
65 }
66 }
67 }
6.线程阻塞(LockSupport)
LockSupport的park()方法可以阻塞当前线程。
LockSupport为每个线程准备一个许可,park()将许可变为不可用;unpark()将许可变为可用。
即使unpark()先执行,在碰到对应的park()也能继续执行。
1 package com.company;
2
3
4 import java.util.concurrent.locks.LockSupport;
5
6 public class User implements Runnable{
7 private static Object o = new Object();
8
9 @Override
10 public void run() {
11 synchronized (o){
12 System.out.println(Thread.currentThread().getName());
13 LockSupport.park();
14 }
15 }
16
17 public static void main(String[] args) throws InterruptedException {
18 User u = new User();
19 Thread t1 = new Thread(u);
20 Thread t2 = new Thread(u);
21 t1.start();
22 t2.start();
23 24 LockSupport.unpark(t2);
25 t1.join();
26 t2.join();
27 }
28 }
park()还可以响应中断。
1 package com.company;
2
3
4 import java.util.concurrent.locks.LockSupport;
5
6 public class User implements Runnable{
7 private static Object o = new Object();
8
9 @Override
10 public void run() {
11 synchronized (o){
12 LockSupport.park();
13 if(Thread.interrupted()){
14 System.out.println("线程中断了");
15 }
16 }
17 }
18
19 public static void main(String[] args) throws InterruptedException {
20 User u = new User();
21 Thread t1 = new Thread(u);
22 t1.start();
23 t1.interrupt();
24 }
25 }
7.限流算法
- 漏桶算法

- 令牌桶算法(Guava的RateLimiter)

1 import com.google.common.util.concurrent.RateLimiter;
2
3 public class User implements Runnable{
4 //设定每秒处理2个请求
5 static RateLimiter t = RateLimiter.create(2);
6
7 public void run() {
8 System.out.println(System.currentTimeMillis());
9 }
10
11 public static void main(String[] args) {
12 for (int i = 0; i < 50; i++) {
13 t.acquire();
14 new Thread(new User()).start();
15 }
16 }
17 }
来源:https://www.cnblogs.com/vshen999/p/12404615.html