多线程与高并发三 各种JUC 同步锁(JAVA中线程类)

ReentrantLock 可重入锁

ReentrantLock 可以自己控制 tryLock 方法 锁不上的情况

lockInterruptibly 方法  上锁的时候被打断怎么办

 

ReentrantLock 公平锁和非公平锁,synchronized 只有非公平锁

 

CountDownLatch

static void countDownLatchTest(){
        Thread[] threads = new Thread[100];
        CountDownLatch countDownLatch = 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;
                countDownLatch.countDown(); //原子性 自减
            });
        }

        for(int j = 0; j < threads.length; j++){
            threads[i].start();
        }

        try {
            countDownLatch.wait(); //阻塞线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

这里的length 是100。

countDownLatch.wait();  前面的代码都执行,到这行时进行阻塞,和join差不多,阻塞。

阻塞到什么时候 进行后续的代码执行呢,

for(int j = 0; j < 10000;j++) result += j;
countDownLatch.countDown(); //原子性 自减

for循环走完,然后countdown 自减,自减到0的时候,阻塞结束,执行 wait()后续代码。

和join很像

 

CyclicBarrier

 CyclicBarrier barrier = new CyclicBarrier(20,()->{
            System.out.println("  ok ");
        });
//        CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("  达到20 个了");
//            }
//        });

        for(int i = 0; i < 100; i++){
            new Thread(()->{
                try {
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

阻塞。阻塞到指定数量时干某件事。如果只对 CyclicBarrier 指定数量而没有传入 run(){} 的实现,则不做任何事。

 

Phaser

public class MyThread {

    static Random r = new Random();
    static MyPhaser phaser = new MyPhaser();

    static void milliSleep(int mill){
        try {
            TimeUnit.MICROSECONDS.sleep(mill);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        phaser.bulkRegister(7);

        for (int i = 0;i < 5;i++){
            final int nameIndex = i;
            new Thread(new Person("p" + nameIndex)).start();
        }

        new Thread(new Person("新郎")).start();
        new Thread(new Person("新娘")).start();
    }

    static class Person implements Runnable{
        String name = "";

        Person(String name){
            this.name = name;
        }

        void arrive(){
            milliSleep(r.nextInt(1000));
            System.out.printf(" %s 到达了",name);
            System.out.println();
            phaser.arriveAndAwaitAdvance();
        }

        void eat(){
            milliSleep(r.nextInt(1000));
            System.out.printf("%s 吃饭 ",name);
            System.out.println();
            phaser.arriveAndAwaitAdvance();
        }

        void leave(){
            milliSleep(r.nextInt(1000));
            System.out.printf("%s 离开" , name);
            System.out.println();
            phaser.arriveAndDeregister();
        }

        void hug(){
            if(name.equals("新郎") || name.equals("新娘")){
                milliSleep(r.nextInt(1000));
                System.out.printf("  %s  新郎 新娘一起回家",name);
                phaser.arriveAndAwaitAdvance();
            }else{
                System.out.println(name + "回家");
                phaser.arriveAndDeregister();
            }
        }

        @Override
        public void run() {
            arrive();

            eat();

            leave();

            hug();
        }
    }

    static class MyPhaser extends Phaser{
        @Override
        protected boolean onAdvance(int phase, int registeredParties) {
            //phase  设定要进行某个业务逻辑的 指令。
            switch (phase){
                case 0:
                    System.out.println(" 婚礼完成");
                    return false;//返回false,保证可以继续执行后续操作
                case 1:
                    System.out.println(" 吃饭结束 ");
                    return false;
                case 2:
                    System.out.println(" 参加婚礼的各自回家");
                    return true;
                default:
                    return true;
            }
        }
    }
}

满足多场景业务使用

onAdvance  return false ,则后续逻辑可以进行,不会退出。return true 则执行完毕。
phaser.arriveAndDeregister();  执行 onAdvance 方法中后续的case。

 

ReadWriteLock  读写锁、排它锁。
public class MyThread {

    static Lock lock = new ReentrantLock();
    static int value;

    static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    static Lock readLock = readWriteLock.readLock();
    static Lock writeLock = readWriteLock.writeLock();

    static void read(Lock lock){
        lock.lock();
        try {
            Thread.sleep(1000);
            System.out.println(" read over " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    static void write(Lock lock,int v){
        lock.lock();
        try {
            Thread.sleep(1000);
            value = v;
            System.out.println(" write over");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {

        Runnable read = ()->read(lock);
        Runnable write = ()->write(lock,new Random().nextInt());

        for(int i = 0;i<18;i++) new Thread(read).start();
        for(int i = 0;i<2;i++) new Thread(write).start();


    }


}

修改下main

Runnable read = ()->read(readLock);
        Runnable write = ()->write(writeLock,new Random().nextInt());

效率明显提升。

readlock: 共享锁,读的时候大家都可以读。

writelock:排它锁,写的时候只能一个在写。

写的时候如果不加锁,会造成脏读。读到一半读到了别人刚写到一半的数据。

 

Semaphore
public static void main(String[] args) {

        Semaphore semaphore = new Semaphore(1);

        new Thread(()->{
            try {
                semaphore.acquire();

                System.out.println(" T1  running ");
                Thread.sleep(200);
                System.out.println(" T1  running ");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                semaphore.acquire();

                System.out.println(" T2  running ");
                Thread.sleep(200);
                System.out.println(" T2  running ");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }

当  Semaphore semaphore = new Semaphore(1);

当  Semaphore semaphore = new Semaphore(2);

所以 Semaphore 的作用就是,同时允许线程执行的数量。设置1则只能同时一个线程执行,2就是两个,10就是10个。

 

Exchanger
static Exchanger<String> exchanger = new Exchanger<>();

    public static void main(String[] args) {

        new Thread(()->{
            String s = "T1";
            try {

                s = exchanger.exchange(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " " + s);
        },"t1").start();

        new Thread(()->{
            String s = "T2";
            try {

                s = exchanger.exchange(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " " + s);
        },"t2").start();

    }

两个线程之间进行阻塞,然后进行线程数据交换。

三个线程的时候,第三个线程进行阻塞,等待第四个。

所有  Exchanger 是两两交换。先进去的两个线程进行交换。

 

LockSupport
Thread t = new Thread(()->{
            for(int i = 0; i < 10;i++){
                System.out.println(i);
                if(i == 5){
                    LockSupport.park();//停止
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        t.start();

        try {
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(" go ");
        LockSupport.unpark(t); //继续

 

LockSupport 暂停或唤醒某个线程。不需要使用synchronized ,不用wait 和 notify。 
unpark 可以先于 park 调用,并且有效。 notify 先于 wait 则不行。

 

ThreadLocal
public class MyThread {

    static ThreadLocal<Person> t1 = new ThreadLocal<Person>();

    public static void main(String[] args) {

//        StampedLock
//        CountDownLatch
        MyThread m = new MyThread();

        new Thread(()->{
            try {
                TimeUnit.MICROSECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println( t1.get());
        }).start();

        new Thread(()->{
            try {
                TimeUnit.MICROSECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t1.set(new Person());
        }).start();
    }

    static class Person{
        String name = "zhangsan";
    }

 按照逻辑,运行应该是 zhangsan ,实际结果 null

 

set源码

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

出现了一个map,key为线程

就是说,使用  ThreadLocal  的每个线程使用的都是本线程的单独的空间。

ThreadLocal用途: 声明式事务,保证同一个connection

ThreadLocal 用完之后一定要调用 remove() 方法,否则会造成内存泄漏

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值