线程(二)

ReentrantLock 也是CAS

ReentrantLock 支持公平锁和非公平锁,可重入锁 ReentrantLock的底层是通过 AQS 实现。可以替代sync

lock(); unlock(); 加锁与释放锁

package msb.reentranlockp;

import msb.commons.ThreadUtil;

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

public class T01_ReentrantLock2 {

    Lock lock=new ReentrantLock();
    public void  m(){
        try {
          lock.lock();
          ThreadUtil.threadSleep(1000);
            System.out.println(Thread.currentThread().getName());
        }finally {
            lock.unlock();
        }
    }
    public void  m2(){
        try {
            lock.lock();
            ThreadUtil.threadSleep(1000);
            System.out.println(Thread.currentThread().getName());
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        T01_ReentrantLock2 r = new T01_ReentrantLock2();
        new Thread(r::m).start();
        new Thread(r::m2).start();
    }
}

必须使用 unlock 进行释放锁,一般结合 try {}finally { lock.unlock(); } 进行使用,

尝试锁定,

就是尝试去拿锁,进行锁定,不管锁定与否,方法都将继续执行
可以根据 tryLock 的返回直接来判断是否锁定
也可以指定 tryLock 的时间,由tryLock (time) 抛出异常,所以要注意 unlock 的释放

package msb.reentranlockp;

import msb.commons.ThreadUtil;

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

public class T01_ReentrantLock3 {

    Lock lock=new ReentrantLock();
    public void  m(){
        lock.lock();
        for (int i = 0; i < 9; i++) {
            ThreadUtil.threadSleep(1000);
            System.out.println(Thread.currentThread().getName());
        }
        lock.unlock();
    }
    public void  m2(){
        try {
            // 尝试5秒之内拿到锁,返回true 就是拿到,返回false 就是没拿到
            // 无论返回什么,都不影响代码继续运行,
            boolean b = lock.tryLock(5, TimeUnit.SECONDS);
              // boolean b = lock.tryLock( );//没有时间执行代码,就会立即去尝试获取锁
            System.out.println(b);
            lock.unlock();// 如果不是放锁,其他线程就拿不到锁,
            // 如果没拿到锁,还要执行释放锁 代码异常java.lang.IllegalMonitorStateException
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        T01_ReentrantLock3 r = new T01_ReentrantLock3();
        new Thread(r::m).start();
        ThreadUtil.threadSleep(1000);
        new Thread(r::m2).start();
        ThreadUtil.threadSleep(1000);
        new Thread(r::m).start();
    }
}

可被打断的锁 lockInterruptibly

睡眠的线程不能被打断,可以打断长时间因为获取不到锁 ,而在等待的线程, 被加锁正在运行的线程是无法打断的

package msb.reentranlockp;

import msb.commons.ThreadUtil;

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

/**
 * 可被打断的锁
 */
public class T01_ReentrantLock4 {

    static  Lock  lock=new ReentrantLock();
    public void  m(){
        lock.lockInterruptibly();
        for (int i = 0; i < 9; i++) {
            // 测试时间过长
            ThreadUtil.threadSleepF(30);
            System.out.println(Thread.currentThread().getName());
        }
        lock.unlock();
    }
    public void  m2(){
        try {
           lock.lockInterruptibly();//可被中断的锁
            System.out.println("调用线程t2.interrupt();,我被中断了");
            System.out.println("调用线程t2.interrupt(),我被中断了");
            System.out.println("调用线程t2.interrupt(),我被中断了");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        T01_ReentrantLock4 r = new T01_ReentrantLock4();
        Thread thread = new Thread(r::m);
        thread.start();
        ThreadUtil.threadSleep(1000);
        System.out.println("进行打断线程1");
        thread.interrupt();
        System.out.println("启动m2线程");
        Thread t2 = new Thread(r::m2);
        t2.start();
        //等待3秒进行打断
        ThreadUtil.threadSleep(3000);
        System.out.println("进行打断");
        t2.interrupt();// 线程调用 进行中断获取锁,获取不到锁,就中断,不用等待了
        ThreadUtil.threadSleep(1000);

    }
}

公平锁和非公平锁

公平: 其他线程获取锁去等待队列里面排队
非公平:其他线程获取锁直接去抢锁

package msb.reentranlockp;

import msb.commons.ThreadUtil;

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

/**
 * 公平锁和非公平锁
 */
public class T01_ReentrantLock5 {

    static Lock lock = new ReentrantLock( );

    public void m() {
        try {
            for (int i = 0; i < 1000; i++) {
                lock.lock();
                System.out.println(Thread.currentThread().getName());
                lock.unlock();
            }
        } catch ( Exception e) {
            e.printStackTrace();
            lock.unlock();
        }

    }



    public static void main(String[] args) {
        T01_ReentrantLock5 r = new T01_ReentrantLock5();
        Thread t1 = new Thread(r::m);
        Thread t2 = new Thread(r::m);
        t1.start();
        t2.start();

    }
}

CountDownLatch 门栓

package msb.countdown;

import java.util.concurrent.CountDownLatch;

/**
 *  CountDownLatch
 *  门栓
 */
public class CountDown {
    public static void main(String[] args) {
        usingCountDownLatch();
    }  
    private static void usingCountDownLatch(){
       Thread [] threads = new Thread[100];//定义100个线程
        CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
        //CountDownLatch latch = new CountDownLatch(200);//定义一个数量,

        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();//每个线程创建完成, latch-1
              //  latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
            });
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();//启动线程
        }
        try {
            latch.await(); //线程等待.等待latch 数到0 继续执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("end");
    }
}

 CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
 如果定义200,循环 100个线程,代码是不会输出end,不会停止,
 如果定义小于100,则会提前输出吧,
 如果每次调用两次 latch.countDown(); 每次则减少2
   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();//每个线程创建完成, latch-1
              //  latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
            });
        }
package msb.countdown;

import java.util.concurrent.CountDownLatch;

/**
 *  CountDownLatch
 *  门栓
 */
public class CountDown {
    public static void main(String[] args) {
       // usingCountDownLatch();
        usjoin();
    }
    private static void usingCountDownLatch(){
       Thread [] threads = new Thread[100];//定义100个线程
        CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
        //CountDownLatch latch = new CountDownLatch(200);//定义一个数量,

        for (int i = 0; i < threads.length; i++) {

           threads[i] = new Thread(()->{
               int result = 0;
                for (int j = 0; j < 100; j++) {
                    result +=j;
                }
                latch.countDown();//每个线程创建完成, latch-1
              //  latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
            });
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();//启动线程
        }
        try {
            latch.await(); //线程等待.等待latch 数到0 继续执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("end");
    }

    private static  void usjoin(){
        Thread [] threads=new Thread[100];
        for (int i = 0; i < threads.length; i++) {
            threads[i] =new Thread(()->{
                for (int j = 0; j < 10; j++) {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }

        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(Thread.currentThread().getName());
    }
}

CyclicBarrier

package msb.cyc;

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

/**
 * 栅栏
 */
public class T01_CyclicBarrier {
    public static void main(String[] args) {
     CyclicBarrier barrier= new CyclicBarrier(20)
    //指定多少个线程.执行第二个方法
       CyclicBarrier barrier= new CyclicBarrier(20,new Runnable(){
            @Override
            public void run() {
                System.out.println("满人,发车");
            }
        });
        for (int i = 0; i < 100; i++) {
        // 如果显示线程101循环,只会输出五次,第101个线程,一直等剩余的19个到齐,还会执行
            new Thread(()->{
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

满人,发车
满人,发车
满人,发车
满人,发车
满人,发车

读写锁 (共享锁,排它锁)

读锁:共享锁
写锁:排他锁

package msb.readwritelock;

import msb.commons.ThreadUtil;
import msb.where.T01_WhereIsThread;

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 T01_ReadWriteLock {
   static   ReentrantLock lock=new ReentrantLock();
    static  ReadWriteLock readWriteLock=  new ReentrantReadWriteLock();
    static     Lock readLock = readWriteLock.readLock();
    static   Lock write = readWriteLock.writeLock();

    public static void read(Lock lock){
        lock.lock();
        ThreadUtil.threadSleep(1000);
        System.out.println("reading");
        lock.unlock();
    }
    public static void write(Lock lock,int value){
        lock.lock();
        ThreadUtil.threadSleep(1000);
        System.out.println("write");
        lock.unlock();
    }

    public static void main(String[] args) {

      Runnable readR =  ()->read(lock); // 如果使用lock 锁 每个都是获取一把锁
     // Runnable readR =  ()->read(readLock); // 使用读锁.可以共享
      Runnable writeW =  ()->write(lock,3); // 使用写锁,是单独的一把锁,不释放,其他线程没办法执行
     // Runnable writeW =  ()->write(write,3);
        for (int i = 0; i <18 ; i++) {
            new Thread(readR).start();
        }
        for (int i = 0; i <2 ; i++) {
            new Thread(writeW).start();
        }
    }
}

Semaphore

通行证,买票

package msb.semaphore;

import msb.commons.ThreadUtil;

import java.util.concurrent.Semaphore;

public class T01_SemaPhore {
  static   Semaphore s = new Semaphore(2);//
 // static   Semaphore s = new Semaphore(1,true);// 公平锁

    public static void main(String[] args) {

        new Thread(()->{

            try {
                s.acquire(4);// 拿到一个通行证
               // s.acquire(n);// 拿到一个通行证 如果只有2个通行证,想要获取两个以上,就会一直等待获取.程序不会向下运行,但是其他线程满足获取的通行证就可以进行运行
                System.out.println("r1");
                ThreadUtil.threadSleep(800);
                System.out.println("r1");
                 s.release(4);
               // s.release(x);//释放一个通行证
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(()->{

            try {
                s.acquire(2);
                System.out.println("r2");
                ThreadUtil.threadSleep(800);
                System.out.println("r2");
                s.release(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

ExChange 交换

两个线程进行交换
如果另外一个线程不进行exchange 的话,就一直等待另个一个线程交换 (给你换东西,你必须给我一个.要不然不罢休)。
都是两两线程进行交换

package msb.exchange;

import java.util.concurrent.Exchanger;

public class T01_Exchange {
    static Exchanger<String> e = new Exchanger<>();

    public static void main(String[] args) {
        new Thread(()->{
            String s="name";
            try {
             s=   e.exchange( s);
                System.out.println(s +"  " + Thread.currentThread().getName());
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        },"T1").start();
//        new Thread(()->{
//
//            String s="age";
//            try {
//                s=   e.exchange( s);
//                System.out.println(s +"  " + Thread.currentThread().getName());
//            } catch (InterruptedException interruptedException) {
//                interruptedException.printStackTrace();
//            }
//        },"T2").start();

        String s="age";
        try {
            s=   e.exchange( s);
            System.out.println(s +"  " + Thread.currentThread().getName());
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
    }
}

四线程进行交换,奇数线程进行交换的话,肯定是有一个线程在等待另外一个线程在等待

package msb.exchange;

import java.util.concurrent.Exchanger;

public class T01_Exchange {
    static Exchanger<String> e = new Exchanger<>();

    public static void main(String[] args) {
        new Thread(()->{
            String s="我是t1";
            try {
             s=   e.exchange( s);
                System.out.println(  Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        },"T1").start();
        new Thread(()->{

            String s="我是t2";
            try {
                s=   e.exchange( s);
                System.out.println(  Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        },"T2").start();


        new Thread(()->{

            String s="我是t3";
            try {
                s=   e.exchange( s);
                System.out.println(  Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        },"T3").start();

        String s="我是mian";
        try {
              s=   e.exchange( s);
            System.out.println(  Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
        } catch ( Exception interruptedException) {
            interruptedException.printStackTrace();
        }
    }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值