多线程与高并发8

1、ReentrantLock打断锁机制

ReentrantLock还可以lock.lockInterruptibly()这个方法,对interrupt()方法做出相应,可以被打断的加锁。

比如t1线程调用了lock.lockInterruptibly(),一直sleep。我们可以调用t2.interrupt。从而打断t2线程的等待。使用原来的lock.lock()是无法打断的。这就是ReentrantLock比synchronized好用的地方

package com.example.demo.gc20;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class T04_ReentrantLock4 {
    // RenntrantLock的锁打断机制
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Thread t1 = new Thread( () ->{
            try {
                lock.lock();
                System.out.println("t1 start");
                TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                System.out.println("t1 end");
            }catch (InterruptedException e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
           try {
               lock.lockInterruptibly();
               System.out.println("t2 start");
               TimeUnit.SECONDS.sleep(5);
               System.out.println("t2 stop");
           }catch (InterruptedException e){
               System.out.println("InterruptedException");
           }finally {
               lock.unlock();
           }
        });
        t2.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        t2.interrupt(); // 打破t2线程等待
    }
}

在这里插入图片描述

2、公平锁与非公平锁

ReentrantLock可以指定为公平锁。它默认是非公平的。
公平锁的意思是当我们new一个ReentrantLock可以传参数true。true为公平锁。false为非公平锁
公平锁:谁等在前面就先让谁执行。

package com.example.demo.gc20;

import java.util.concurrent.locks.ReentrantLock;

public class T05_ReentrantLock5 extends Thread {
    // 公平锁
    private static ReentrantLock lock = new ReentrantLock(true);

    public void run(){
        for(int i=0;i<100;i++){
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+"获得锁");
            }finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        T05_ReentrantLock5 t5 = new T05_ReentrantLock5();
        Thread t1 = new Thread(t5);
        Thread t2 = new Thread(t5);
        t1.start();
        t2.start();
    }
}

在这里插入图片描述

####ReentrantLock vs synchronized
ReentrantLock可以替代synchronized是没有问题的。他也可以重入。可以锁定。本身底层是cas。
trylock:自己来控制
lockInterruptibly:指定当前线程中间可以被打断
interrupt:线程停止等待

现在除了synchronized之外,多数内部都是用cas。这个lock不像sync那样直接进入阻塞状态。至少前面还有一个cas状态

3、CountDownLatch(倒数门栓)

package com.example.demo.gc20;

import java.util.concurrent.CountDownLatch;

public class T06_TestCountDownLatch {
    // 倒数门栓
    public static void main(String[] args) {
        usingJoin();
        usingCountDownLatch();
    }

    private static void usingCountDownLatch() {
       Thread [] threads = new Thread[100];
        CountDownLatch latch = new CountDownLatch(threads.length);
        for (int i=0;i<threads.length;i++){
            threads[i] = new Thread(() -> {
               int result = 0;
               for (int j=0;j<10000;j++){
                   result += j;
                   latch.countDown();
               }
            });
        }
        for (int i = 0;i<threads.length;i++){
            threads[i].start();
        }
        try {
            latch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("end latch");
    }

    private static void usingJoin(){
        Thread[]threads = new Thread[100];
        for (int i=0;i<threads.length;i++){
            threads[i] = new Thread(() ->{
               int result = 0;
               for (int j=0; j<10000;j++){
                   result += j;
               }
            });
        }
        for (int i=0;i<threads.length;i++){
            threads[i].start();
        }
        for(int i = 0;i<threads.length;i++){
            try{
                threads[i].join();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println("end join");
    }
}

在这里插入图片描述
####join和倒数门栓的用法区别。
join用法没那么灵活。就是哪个线程在当前线程执行后调用join方法。就它执行完毕后当前线程再执行。
而倒数门栓是。new 一个倒数门栓计数。每一个线程结束就latch.countdown()也就是count–。这时候程序一直在latch.await()这里。插着就插着。并且计数。100,99,98这样。一直到count为0的时候,门栓才会被打开。它是用来等待线程结束

4、cyclicBarrier(循环栅栏)

使用场景:我们需要并发执行,不同线程去执行不同操作。有的线程去数据库操作,有的线程去网络访问。有的线程去读文件。必须是这三个线程都到位了以后。才能执行操作。这时候就可以用cyclicBarrier

package com.example.demo.gc20;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class T07_TestCyclicBarrier {
    // 循环栅栏
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(20,() ->
                System.out.println("满人"));
        for (int i=0;i<100;i++){
            new Thread(() -> {
                try {
                    barrier.await();
                }catch (InterruptedException e){
                    e.printStackTrace();
                }catch (BrokenBarrierException e){
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值