52、Java JUC

1、java高级语法、java集合类 、Java多线程 、java IO

一、Lamda 表达式口诀:复制小括号,写死箭头号,落地大括号

接口还可以这样写

 

 测试Lambda表达式,接口的默认方法,接口的静态方法

public class LambdDemo {

    public static void main(String[] args) {
        Foo foo = (int x ,int y) -> {
            System.out.println(" ++++++come in here ");
            return x+y;
        };
        System.out.println(foo.sayHello(3, 4));
        System.out.println(foo.mv(3, 5));

        System.out.println(Foo.div(4, 5));
    }
}

二、JUC的 Lock 锁的使用 实现高并发、多线程访问资源类

声明资源类

class Ticket {
    int number = 30;

    private Lock lock = new ReentrantLock();

    public void saleTicket() {
        try{
            lock.lock();
            if (number >0 ){
                System.out.println(Thread.currentThread().getName()+"线程\t买出的票"+(number--)+"还剩下的票:"+ number);
            }
        }finally {
            lock.unlock();
        }
    }

}

测试多线程访问资源类

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(()->{
            for(int i=1;i<40;i++) {
                ticket.saleTicket();
            }
        },"A").start();
        new Thread(()->{
            for(int i=1;i<40;i++) {
                ticket.saleTicket();
            }
        },"B").start();
        new Thread(()->{
            for(int i=1;i<40;i++) {
                ticket.saleTicket();
            }
        },"C").start();
    }

 3、线程之间的通信 

使用:synchronized、notifyAll,wait 实现线程之间的通信

编写资源类

class Air {
    int number = 0;

    public synchronized void increment () throws InterruptedException {
        while (number != 0) {
            this.wait();
        }
        //干活
        number++;
        System.out.println(Thread.currentThread().getName()+"\t"+ number);
        //唤醒其他线程
        this.notifyAll();
    }

    public synchronized void decrement() throws InterruptedException {
        while (number == 0) {
            this.wait();
        }
        //干活
        number--;
        System.out.println(Thread.currentThread().getName()+"\t"+ number);
        //唤醒其他线程
        this.notifyAll();
    }
}

测试多线程调用资源类

public static void main(String[] args) throws Exception{
        Air air = new Air();
        new Thread(()->{
            try {
                for (int i =1;i<=10;i++){
                    air.increment();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        new Thread(()->{
            try {
                for (int i =1;i<=10;i++){
                    air.increment();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"B").start();
    }

使用:Lock、condition.await();,condition.signalAll();实现线程之间的通信

编写资源类

class AirMode {
    private int number = 0;

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void increment() {
       try {
           lock.lock();
           while (number != 0) {
               condition.await();//this.wait
           }
           number ++;
           System.out.println(Thread.currentThread().getName()+"\t: "+ number);
           condition.signalAll();//this.notifyAll
       }catch (InterruptedException e){
           e.printStackTrace();
       }
       finally {
           lock.unlock();
       }
    }
    public void decrement() {
        try {
            lock.lock();
            while (number == 0) {
                condition.await();//this.wait
            }
            number --;
            System.out.println(Thread.currentThread().getName()+"\t: "+ number);
            condition.signalAll();//this.notifyAll
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        finally {
            lock.unlock();
        }
    }
}

测试JUC多线程调用资源类

public static void main(String[] args) {
        AirMode airMode = new AirMode();
        new Thread(()->{
            for(int i = 1;i<=10; i++) {
                airMode.increment();
            }
        },"A").start();
        new Thread(()->{
            for(int i = 1;i<=10; i++) {
                airMode.decrement();
            }
        },"B").start();
        new Thread(()->{
            for(int i = 1;i<=10; i++) {
                airMode.increment();
            }
        },"C").start();
        new Thread(()->{
            for(int i = 1;i<=10; i++) {
                airMode.decrement();
            }
        },"D").start();
    }

使用:Lock、condition.await();,condition.signal();实现线程之间的通信并且精准通知

编写资源类

class ShareResource {
    //标志位
    private int number = 1; //A->1 B->2 C->3
    private Lock lock = new ReentrantLock();
    private Condition condition1 = lock.newCondition();
    private Condition condition2 = lock.newCondition();
    private Condition condition3 = lock.newCondition();

    public void print5() {
        lock.lock();
        try {
            while (number != 1){
                condition1.await();
            }
            for (int i =1;i<=5;i++){
                System.out.println(Thread.currentThread().getName()+"线程"+"第"+i+"次");
            }
            number = 2;
            condition2.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void print10() {
        lock.lock();
        try {
            while (number != 2){
                condition2.await();
            }
            for (int i =1;i<=10;i++){
                System.out.println(Thread.currentThread().getName()+"线程"+"第"+i+"次");
            }
            number = 3;
            condition3.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    public void print15() {
        lock.lock();
        try {
            while (number != 3){
                condition3.await();
            }
            for (int i =1;i<=15;i++){
                System.out.println(Thread.currentThread().getName()+"线程"+"第"+i+"次");
            }
            number = 1;
            condition1.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

测试线程之间的精准通知

 public static void main(String[] args) {
        ShareResource shareResource = new ShareResource();
        for (int i=1;i<3;i++){
            new Thread(()->{
                shareResource.print5();
            },"A").start();
            new Thread(()->{
                shareResource.print10();
            },"B").start();
            new Thread(()->{
                shareResource.print15();
            },"C").start();
        }
    }

4、多线程8锁 详解

编写资源类

class Phone {

    public synchronized void sendEmail() {
        try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println("============sendEmail=============");
    }

    public synchronized void sendSMS() {
        System.out.println("============sendSMS=============");
    }

    public void hello () {
        System.out.println("============hello=============");
    }
}

测试运行结果

/**
 * 1、 同一部手机,先打印发邮件还是发短信
 * 2、两部部手机,先打印发邮件还是发短信
 * 3、同一部手机,A调用同步方法,B调用普通方法,先打印发邮件还是发短信
 * 4、同一部手机,A调用静态同步方法,B调用静态同步方法,先打印发邮件还是发短信
 * 5、两部手机,A调用静态同步方法,B调用静态同步方法,先打印发邮件还是发短信
 * 6、同一部手机,A调用静态同步方法,B调用普通同步方法,先打印发邮件还是发短信
 * 7、两部部手机,A调用静态同步方法,B调用普通同步方法,先打印发邮件还是发短信
 */
public class Lock8 {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();
        new Thread(() ->{
            phone1.sendEmail();
        },"A").start();

        new Thread(() ->{
            phone2.sendSMS();
            //phone2.sendSMS();
            //phone1.hello();
        },"B").start();
    }
}

总结:要搞清楚锁的是哪里

1、普通同步方法锁的是当前对象

2、静态同步方法锁的是当前模板类,Class

3、普通方法锁不参与多线程竞争

5、多线程的创建方式,继承Thread,实现Runable,实现Callable

以实现Callable

class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("============= come in ===============");
        return 1024;
    }
}

测试调用

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask(new MyThread());
        new Thread(futureTask,"A").start();
        System.out.println("===============计算完成==============");
        System.out.println(futureTask.get());
    }

6、控制线程的执行顺序

CountDownLatch 的使用

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i=1;i<=6;i++){
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t 离开走人");
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName()+"\t 班长走人");
    }

CyclicBarrier 的使用

public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("============召唤神龙");
        });

        for (int i =1;i<=7;i++){
            final int tempInt = i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"\t 获得第"+ tempInt+"颗龙珠");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }

Semaphore 的使用

 public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        for(int i =1;i<=6;i++) {
            new Thread(()->{
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"\t 抢占到车位");
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+"\t 离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }

ReadWriteLock 的使用,在写的时候要求数据的一致性不能被别的线程打断,在读取数据的时候可以多个线程同时读

编写资源类

class MyCache {
    private volatile Map<String,Object> map = new HashMap<>();

    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void put(String key,Object value) {
        try{
            readWriteLock.writeLock().lock();
            System.out.println(Thread.currentThread().getName()+"\t ------写入数据中");
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException ex) { ex.printStackTrace(); }
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"\t ------写入数据完成");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();
        }

    }
    public void get(String key){
        try{
            readWriteLock.readLock().lock();
            System.out.println(Thread.currentThread().getName()+"\t 读取数据中");
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException ex) { ex.printStackTrace(); }
            Object value = map.get(key);
            System.out.println(Thread.currentThread().getName()+"\t 读取数据完成");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            readWriteLock.readLock().unlock();
        }
    }
}

测试ReadWriteLock 

 public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for(int i=1;i<=5;i++) {
            int tempInt = i;
            new Thread(()->{
                myCache.put(Thread.currentThread().getName(),tempInt);
            },String.valueOf(i)).start();
        }
        for(int i=1;i<=5;i++) {
            int tempInt = i;
            new Thread(()->{
                myCache.get(Thread.currentThread().getName());
            },String.valueOf(i)).start();
        }
    }

7、线程池的使用

三个常用的线程池

 

 线程池的七个重要参数

 

 线程池的原理见图

 工作中手写线程池

public static void main(String[] args) {
        ExecutorService threadPoll = new ThreadPoolExecutor(
                2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try{
            for (int i =1;i<=8; i++){
                threadPoll.execute(()->{
                    System.out.println(Thread.currentThread().getName()+ "\t 办理业务!");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPoll.shutdown();
        }
    }

9、 四大函数式接口

 链式编程的写法

@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class Book {

    private Integer id;
    private String bookName;
    private double price;

    public static void main(String[] args) {
        Book book = new Book();
        book.setId(1).setBookName("Java").setPrice(30.3d);
        System.out.println(book.toString());
    }
}

 

 10、Stream 的流式计算

filter、map、sorted、limit 的使用

 11、异步回调  CompletableFuture 的使用

 

posted @ 2021-07-07 15:55  shunnWcs  阅读(80)  评论(0)    收藏  举报