常见的锁机制及案列使用(util.concurrent)

CountDownLatch 闭锁

是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

package study;


import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        new Thread(new Server2(countDownLatch)).start();
        for (int i = 0; i < 10; i++) {
            new Thread(new Server(countDownLatch)).start();
        }
    }
}

class Server implements Runnable {
    private CountDownLatch myCount;

    public Server(CountDownLatch myCount) {
        this.myCount = myCount;
    }

    @Override
    public void run() {
        //递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.
        myCount.countDown();
        System.out.println("一个server1运行完了 还剩" + myCount.getCount());
    }
}

class Server2 implements Runnable {
    private CountDownLatch myCount;

    public Server2(CountDownLatch myCount) {
        this.myCount = myCount;
    }

    @Override
    public void run() {
        try {
            System.out.println("正在等待N个server1运行完毕");
            myCount.await();
            System.out.println("N个server1运行完毕");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void countDown()

  递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.

public boolean await(long timeout,TimeUnit unit) throws InterruptedException

  使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。如果当前计数为零,则此方法立刻返回true值。

CyclicBarrier 栅栏锁

CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使。它可以使用reset()方法重置。

package study;


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

public class CyclicBarrierTest {

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println("所有线程已经结束");
            }
        });
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                new Thread(new Server(cyclicBarrier)).start();
            } else {
                new Thread(new Server2(cyclicBarrier)).start();
            }
        }
    }

}

class Server implements Runnable {
    CyclicBarrier cyclicBarrier;

    public Server(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            System.out.println("一个server1到达栅栏");
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            //如果一个线程处于等待状态时,如果其他线程调用reset(),或者调用的barrier原本就是被损坏的,则抛出BrokenBarrierException异常
            e.printStackTrace();
        }
    }
}

class Server2 implements Runnable {
    CyclicBarrier cyclicBarrier;

    public Server2(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            System.out.println("一个server2到达栅栏");
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            //如果一个线程处于等待状态时,如果其他线程调用reset(),或者调用的barrier原本就是被损坏的,则抛出BrokenBarrierException异常
            e.printStackTrace();
        }
    }
}

输出结果会有两组 说明了CyclicBarrier是可以复用的。

注意:这几种情况 所有的CyclicBarrier阻塞的线程全部会被唤醒往下走

最后一个线程到达,即index == 0
某个参与线程等待超时
某个参与线程被中断
调用了CyclicBarrier的reset()方法

当有任何一个线程中断了,非正常运行完,会抛出异常并唤醒其他线程,其他线程醒来后,也会抛出异常。CyclicBarrier处于损坏状态

交换机:两个线程运行到某处可以交换对象 运用场景比较少
 


public class TestExchanger {
    public static void main(String[] args) {
        Exchanger exchanger = new Exchanger();
        ExchangerRunnable exchangerRunnable1 =
                new ExchangerRunnable(exchanger, "A");
       ExchangerRunnable2 exchangerRunnable2 =
                new ExchangerRunnable2(exchanger, "B");
        new Thread(exchangerRunnable1).start();
        new Thread(exchangerRunnable2).start();
    }
}

class ExchangerRunnable implements Runnable {
    Exchanger exchanger = null;
    Object object = null;

    public ExchangerRunnable(Exchanger exchanger, Object object) {
        this.exchanger = exchanger;
        this.object = object;
    }

    @Override
    public void run() {
        Object previous = this.object;
        try {
            System.out.println("进入1");
            this.object = this.exchanger.exchange(this.object);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " exchanged " + previous + " for " + this.object);
    }
}

class ExchangerRunnable2 implements Runnable {
    Exchanger exchanger = null;
    Object object = null;

    public ExchangerRunnable2(Exchanger exchanger, Object object) {
        this.exchanger = exchanger;
        this.object = object;
    }

    @Override
    public void run() {
        Object previous = this.object;
        try {
            //这里会睡眠10s 那么线程1也因此被阻塞10s
            Thread.sleep(10000);
            System.out.println("进入2");
            this.object = this.exchanger.exchange(this.object);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " exchanged " + previous + " for " + this.object);
    }
}

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值