线程同步工具使用

ReentrantLock

  1. 特点:
    • 可重入
    • 可中断:可对正在执行的线程进行中断
    • 可限时:可以设置在多少时间单位内没有获取到资源则执行其他业务方法
    • 公平锁:避免产生饥饿现象,但是性能会降低
  2. 重入锁实现:
    • cas状态:判断当前锁是否被占用
    • 等待队列:将所有在等待状态的线程都保存在队列中
    • park():对进入队列的线程进行挂起,当拥有锁的线程释放完锁后,会调用unpark()启动队列的第一个线程进行资源访问。
    • 说明:重入锁也可以称为递归锁,当外层方法获取到锁时,在锁内的代码段或时方法都会默认的获取到锁,那获取到锁的线程就和进入任何一个已经拥有锁的代码。
  3. 补充:synchroized关键字也是重入锁,但确是非公平锁,jdk1.5后对synchroized进行了优化,所以二者没有太多的差别。

Condition

  1. 概述
    • 类似于Object.wait()和Object.notify()
    • 与 ReentrantLock结合使用

Semaphore

  1. 概述:
    • 共享锁
    • 运行多个线程进入临界去,当只允许一个线程进入时就可以当作普通锁来使用
    • 可以使用在某些不能支持太多请求的系统中,使用共享锁设置具体容量,超过容量的线程就进入等待状态

ReadWriteLock

  1. 增加并行度(读不加锁写枷锁)
  2. 当没有写的功能的情况下读线程是无等待的并发
  3. 读-读不互斥:读读之间不阻塞
  4. 读-写互斥:读阻塞写,写也会阻塞读
  5. 写-写互斥:写写阻塞。

CountDownLatch

  1. 倒数计时器:顾名思义,通过用户自定义一个线程数count,在执行线程时通过倒数计时器对count进行扣减,当count被扣减到0时就会触发倒数计时器在主线程中的等待方法进行放行。
  2. 举例:
public class Test{
    //创建一个倒数计时器当执行完10个线程后就结束
    static final CountDownLatch end=new CountDownLatch(10);

    static final MyThread td=new MyThread();

    public static void main(String[] args) {

       ExecutorService exec=Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10 ; i++) {

            exec.execute(td);

        }
			
		exec.shutdown();
		
        try {
			//该方法使主线程会等待所有的倒计时线程完成之后在执行
            end.await();

        } catch (InterruptedException e) {

            e.printStackTrace();
        }

        System.out.println("发射");


    }

}
class  MyThread implements Runnable{

    public void run(){

        try {

            Thread.sleep(new Random().nextInt(10)*100);

            System.out.println(Thread.currentThread().getName()+"进行了检查");

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //每完成一个线程告诉计时器减1
        Test.end.countDown();
    }
}
执行结果:
pool-1-thread-7进行了检查
pool-1-thread-4进行了检查
pool-1-thread-1进行了检查
pool-1-thread-8进行了检查
pool-1-thread-3进行了检查
pool-1-thread-10进行了检查
pool-1-thread-6进行了检查
pool-1-thread-2进行了检查
pool-1-thread-5进行了检查
pool-1-thread-9进行了检查
发射

CyclicBarrier

  1. 循环栅栏:类似于倒数计时器,但是cylicBarrier则是循环技术,也就是说这个计数器是可以反复使用的,比如:假设我们的计数器设置为10,那么等一批的10个线程执行完成后计数器就会归零,然后接着又筹齐下一批的10个线程,以此来不断对进入的线程进行拦截集合。
  2. 举例:
public class CyclicBarrierTest
{
   //申明一个循环栅栏,第一个参数是设置线程数,第二个参数指的是当凑齐10个线程时触发的线程
   static  final CyclicBarrier barrier=new CyclicBarrier(10,new MyBarrierAction());

   static final MyThread1 td=new MyThread1();

   public static void main(String[] args) {

       ExecutorService exec= Executors.newFixedThreadPool(10);

       for (int i = 0; i < 10 ; i++) {

           exec.execute(td);

       }
       
       exec.shutdown();
       
   }

}
class MyBarrierAction implements Runnable{

   public void run() {

       System.out.println("都集合完毕了");

   }
}

class  MyThread1 implements Runnable{

   public void run(){

       try {
           //等待10个线程集合完毕
           CyclicBarrierTest.barrier.await();

           doWork();

           //等待10个线程都执行完成
           CyclicBarrierTest.barrier.await();

       } catch (InterruptedException e) {

           e.printStackTrace();

       } catch (BrokenBarrierException e) {

           e.printStackTrace();

       }
   }

   private static void doWork() {


       try {

           Thread.sleep(new Random().nextInt(10)*100);

           System.out.println("线程"+Thread.currentThread().getName()+"执行完毕!");

       } catch (InterruptedException e) {

           e.printStackTrace();

       }

   }
}

打印结果:
都集合完毕了
线程pool-1-thread-3执行完毕!
线程pool-1-thread-9执行完毕!
线程pool-1-thread-6执行完毕!
线程pool-1-thread-8执行完毕!
线程pool-1-thread-2执行完毕!
线程pool-1-thread-4执行完毕!
线程pool-1-thread-10执行完毕!
线程pool-1-thread-7执行完毕!
线程pool-1-thread-5执行完毕!
线程pool-1-thread-1执行完毕!
都集合完毕了
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值