企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# lock接口 为锁和等待条件提供一个框架的接口和类,它不同于内置的synchronized同步和monitor监视器。 Lock不是Java语言内置的,是在java.util工具包里面的。需要开发人员手动加锁和解锁。 &nbsp; ## ReentrantLock 可重入锁:同一个线程的不同被锁住的方法可以直接进入。synchronized也是可重入锁,ReentrantLock可以用来替代synchronized,但是需要手动解锁。 ~~~  ReentrantLock lock = new ReentrantLock();  ​  public void method() {      // 上锁   lock.lock();      /*--------------------      * 业务操作      */      // 解锁      // 一定要写在finally代码块中保证会被释放掉      lock.unlock();  } ~~~ 1. tryLock(),在n秒时间内尝试获取锁对象,不管获取与否方法都会继续执行,但是可以根据该方法的返回值来判断是否获取到锁了。 2. lock.lockInterruptibly(),可以被thread.interrupt()打断。 3. new ReetrantLock(true),公平锁。线程会在等待队列中排队等待。如果是非公平的线程会直接抢占锁。多个线程之间会交替执行,而不会让一个线程独占锁。 &nbsp; ## CounDownLatch 当主线程需要在子线程的工作完成后才能继续运行时可以使用这个类进行阻塞。 ~~~  CountDownLatch countDownLatch = new CountDownLathc(2); // 建立2个线程空间  new Thread(() -> {   // 处理   countDownLatch.countDown(); // 值减一  });  countDownLatch.await(); // 阻塞主线程 ~~~ 当countDown的值减为0的时候主线程可以继续往下运行,否则的话阻塞,等待子线程运行完成。 比thread.join()灵活。 &nbsp; ### CyclicBarrier 当线程数达到设定的值的时候就会运行设定的代码。 ~~~  package net.smrobot._thread.day04;  import java.util.concurrent.BrokenBarrierException;  import java.util.concurrent.CyclicBarrier;  public class T07_CyclicBarrierTest {      public static void main(String[] args) {          // 满20人之后调用第二个参数指定的动作          CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {              @Override              public void run() {                  System.out.println("barrier start");             }         });          for (int i = 0; i < 100; i++) {              new Thread(() -> {                  try {                      // 等待,每20个线程才会被放行                      barrier.await();                      System.out.println("11");                 } catch (InterruptedException e) {                      e.printStackTrace();                 } catch (BrokenBarrierException e) {                      e.printStackTrace();                 }             }).start();         }     }  }  ​ ~~~ 可以用在流量限流或者是有个线程要等其他线程结束了才能运行。 > 备注:限流类:Guava RateLimiter &nbsp; ### Phaser 分解段运行,在遗传算法中可以用上。 每个阶段都会设置栈栏。 &nbsp; ### ReadWriteLock 读写锁,当有读线程在读的时候其他线程也可以读数据,写线程等待,而写线程是互斥的。 ~~~  package net.smrobot._thread.day04;  ​  ​  import java.util.Random;  import java.util.concurrent.locks.Lock;  import java.util.concurrent.locks.ReadWriteLock;  import java.util.concurrent.locks.ReentrantLock;  import java.util.concurrent.locks.ReentrantReadWriteLock;  ​  public class T09_ReadWriteLockTest {      static Lock lock = new ReentrantLock();      private static int value;  ​      static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();      static Lock readLock = readWriteLock.readLock();      static Lock writeLock = readWriteLock.writeLock();  ​      public static void main(String[] args) {          // 使用互斥锁  //       Runnable readR = () -> read(lock);  //       Runnable writeR = () -> write(lock, new Random().nextInt());          // 使用读写锁          Runnable readR = () -> read(readLock);          Runnable writeR = () -> write(writeLock, new Random().nextInt());  ​          for (int i = 0; i < 10; i++) {              new Thread(readR).start();         }          for (int i = 0; i < 2; i++) {              new Thread(writeR).start();         }  ​  ​     }  ​      public static void read(Lock lock) {          try {              lock.lock();              Thread.sleep(1000);              System.out.println("read over!");         } catch (InterruptedException e) {              e.printStackTrace();         } finally {              lock.unlock();         }  ​     }  ​      public static void write(Lock lock, int value) {          try {              lock.lock();              Thread.sleep(1000);              value = value;              System.out.println("write over!");         } catch (InterruptedException e) {              e.printStackTrace();         } finally {              lock.unlock();         }     }  }  ​ ~~~ `StampedLock` &nbsp; ### semaphore 信号量,可以用来限流,可以同时设置多少个线程运行。 ~~~  package net.smrobot._thread.day04;  ​  import java.util.concurrent.Semaphore;  ​  public class T10_SemaphoreTest {  ​      public static void main(String[] args) {          Semaphore s = new Semaphore(2);          // 公平锁      //Semaphore s = new Semaphore(2, true);          new Thread(() -> {              try {                  // 信号量中获取锁                  s.acquire();                  System.out.println("t1 running ...");                  Thread.sleep(1000);                  System.out.println("t1 running ....");                  // 释放锁                  s.release();             } catch (InterruptedException e) {                  e.printStackTrace();             }         }).start();  ​          new Thread(() -> {              try {                  s.acquire();                  System.out.println("t2 running ...");                  Thread.sleep(1000);                  System.out.println("t2 running ....");                  s.release();             } catch (InterruptedException e) {                  e.printStackTrace();             }         }).start();  ​     }  }  ​ ~~~ &nbsp; ### Exchanger 用于线程之间通信交换数据,只能用于两个线程之间交换数据,两个线程同时使用exchanger。 ~~~  package net.smrobot._thread.day04;  ​  import java.util.concurrent.Exchanger;  ​  public class T11_ExchangerTest {      static Exchanger<String> exchanger = new Exchanger<>();      public static void main(String[] args) {  ​          new Thread(() -> {              String s1 = "t1";              try {                  s1 = exchanger.exchange(s1);             } catch (InterruptedException e) {                  e.printStackTrace();             }              System.out.println(Thread.currentThread().getName() + s1);         }, "T1").start();  ​          new Thread(() -> {              String s2 = "t2";              try {                  s2 = exchanger.exchange(s2);             } catch (InterruptedException e) {                  e.printStackTrace();             }              System.out.println(Thread.currentThread().getName() + s2);         }, "T2").start();  ​     }  }  ​ ~~~ ### LockSupport 直接使用里面的静态方法,可以暂停某个线程运行与重启。 ~~~  // 暂停线程的运行  LockSupport.park();  ​  // 唤醒线程  LockSupport.unpark(thread); ~~~ 可以先调用unpark(t),此时park()不起作用。