• JDK并发包


    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 }
  • 相关阅读:
    SpringBoot配置文件
    SpringBoot基础开发流程
    day06-01数字类型、数字类型的转换
    特有的循环结构(for-else、while-else)——Python篇
    分支、循环——Python基础篇
    循环关键字——Python篇
    另类三目运算符——Python篇
    原码、反码以及补码
    Python运算符
    Python变量
  • 原文地址:https://www.cnblogs.com/vshen999/p/12404615.html
Copyright © 2020-2023  润新知