3.多线程之JUC并发编程0

1.学习方法 java1.8才有juc 面试高频问

源码+官方文档

2.什么是juc 三个包

java.util.concurrent
java.util.concurrent.atomic
java.util.concurrent.locks

  1. 介绍
  1. Callable性能比Runnable高,并且Runnable没有返回值
  2. 进程和线程
    进程: 一个程序比如QQ.exe
    线程 在QQ里面同时打字和聊天 分别是一个线程
  3. java可以开线程吗?
    不可以 java只能调native方法使用c++调用
  4. 并发和并行
    并发:多线程操作同一资源 cpu 1个核快速交替运行模拟出多线程
    并行: 多个人一起行走 cpu多核多个线程可以同时执行

4.线程有几个状态 6个…代码有但是java课说5个

NEW
RUNNABLE
BLOCK
WAITING
TIMED_WAITING
TERMINATED

4.wait和sleep的区别

  1. 来自不同类
    wait(Object) sleep(Thread)
  2. 锁的释放
    wait释放 sleep抱着锁睡觉
  3. 使用范围不同
    wait必须在同步代码块中使用
    sleep任何地方使用
  4. 是否捕获异常
    wait不需要 (同步代码块中)
    sleep需要 ,会发生超时等待的情况 oop编程面向对象编程

5.Lock锁接口

  1. 实现类
    ReentrantLock true为公平锁 false默认为非公平锁
    ReentrantReadWriteLock.ReadLock读锁
    ReentrantReadWriteLock.WriteLock写锁
  2. 公平锁和非公平锁
    公平:可以先来后到(公平的) 如果3小时的任务后面是3s的任务 非常不公平,公平是相对的…在社会中也是一样…
    非公平(默认):不公平 可以插队

6.Lock三部曲 等待 业务 通知

1.创建资源类(有成员变量和锁)
2.里面加锁 lock 和 unlock
3.main方法创建多个线程.start();操作资源类

7.synchronized和lock的区别

  1. sychronized是java关键字,Lock是java类
  2. sychronized 无法判断锁状态 lock可以判断锁
  3. sychronized自动释放锁 ,lock需要手动释放不让死锁
  4. sychronized线程1得到锁阻塞,线程二傻傻等待释放,lock不一定会等待下去
  5. sychronized可重入锁不可中断,sychronized是否公平锁(由cpu自己决定) ;lock可重入锁,可以判断锁状态非公平(自己设置)
  6. sychronized适合锁少量代码同步问题;Lock锁大量同步代码

8.传统生产者和消费者问题的问题(虚假唤醒问题) 同时开启2个消费者和2个生产者 发现还是不安全
//之前我的困惑是启动了多个消费者和提供者还是会产生超前消费的问题
//,解决把if判断改成while判断资源

while(number!=0){}; //因为if只判断一次,其他线程会唤醒这个线程,所以导致虚假唤醒

public class LightWay {
    public static void main(String[] args) {
        Container1 container1 = new Container1();
        new Producer1(container1).start();
        new Producer1(container1).start();
        new Customer1(container1).start();
        new Customer1(container1).start();

    }
}

class Producer1 extends Thread{
    Container1 container1;
    Producer1(Container1 container1){
        this.container1=container1;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            container1.set(i+"");

        }
    }
}
class Customer1 extends Thread{
    Container1 container1;
    Customer1(Container1 container1){
        this.container1=container1;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {

            try {
                container1.get();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Container1{
    boolean flag=true;
    String thing="";
    public synchronized void set(String thing)  {
        while(!flag){   //改为if为while,不停判断,而不是判断一次
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("生产了"+thing);
        this.thing=thing;
        this.flag=!flag;
        this.notifyAll();

    }
    public synchronized void get() throws InterruptedException {
        while (flag){
            this.wait();
        }
        System.out.println("消费了"+thing);
        this.flag=!flag;
        this.notifyAll();

    }

}

9.JUC的问题: synchronized有wait和notify线程通信,Lock有Condition的await和signal,Lock也用while循环判断

//任何新技术,不是前面技术的覆盖,一定有其优势,我想要 a线程执行完通知b,b执行完通知c
//可以精准通知,如下执行结果为 BCA这样的顺序 可以是BABABA 或者CACACABA执行

public class ConsumerAndProducerJUC1 {
    public static void main(String[] args) {
        TikectAction tikect = new TikectAction();
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                tikect.buy();
            }

        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                tikect.give();
            }

        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 100; i++) {
                tikect.give();
            }

        },"C").start();

    }

}


//资源类 ,包括他的操作要加锁
class TikectAction{
    int num=0;
    ReentrantLock lock=new ReentrantLock();
    Condition condition1= lock.newCondition();
    Condition condition2= lock.newCondition();
    int conditionNum=1;

     void  give(){
        lock.lock();
        try{
            //业务代码
            while (num>0){
                if(conditionNum!=1){
                    condition1.await(); //等待
                }

            }

            num++;
            conditionNum=2;
            System.out.println(Thread.currentThread().getName()+"生产第"+num+"张票");
            condition2.signal(); //通知线程2
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }



    }
    void buy(){
        lock.lock();
        try{
            //业务代码
            while (num<=0){
                if(conditionNum!=2){
                    condition2.await();
                }
            }
            System.out.println(Thread.currentThread().getName()+"消费第"+num+"张票");
            num--;
            conditionNum=1;
            condition1.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }


}

10.八锁问题(本质还是探讨线程和线程,锁与锁 还有加上static或者多个对象和单个对象之间的关系)
!!!run方法是按启动顺序执行的

  1. 标准情况下两个线程的锁方法(不用继承Thread类) 没有锁对象,加了sleep方法的线程后执行
public class eightLockProblems {

    public static void main(String[] args) throws InterruptedException {
        A1 a1 = new A1();
        new Thread(()->{//反正就是sleep后执行,可以运行的先执行
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start();

        new Thread(()->{a1.call();},"call").start();
    }


}
class A1 {

    public  void call(){

        System.out.println("打电话");
    }
    public  void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
    }

}
//,先打电话然后 发短信
  1. synchronize的方法 new2个线程.线程1 : TimeUnit.SECONDS.sleep(1) 线程2: 不写sleep,用的同一个锁对象,一定先执行线程1的
    ,不是执行顺序决定的,而是方法的锁的是对象,谁先拿到谁先执行
public class eightLockProblems {

    public static void main(String[] args) throws InterruptedException {
        A1 a1 = new A1();
        new Thread(()->{//无论执行多少次都是发短信打电话这个顺序,因为他先拿到a1这个锁对象
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start();

        new Thread(()->{a1.call();},"call").start();
    }


}
class A1 {

    public synchronized void call(){

        System.out.println("打电话");
    }
    public synchronized void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
    }

}

3.资源类加个普通方法在线程内调用,执行顺序 先执行普通方法(因为没有资源竞争,不存在锁的问题,锁是要等待的,普通方法不用,所以一直是第一位显示)


public class eightLockProblems {
      //输出  普通方法  发短信 打电话
    public static void main(String[] args) throws InterruptedException {
        A1 a1 = new A1();
        new Thread(()->{//普通方法,没有锁,不存在竞争资源,直接比同步方法先执行
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start();

        new Thread(()->{a1.call();},"call").start();
        new Thread(()->{a1.normalFunc();},"normal").start();
    }


}
class A1 {

    public synchronized void call(){

        System.out.println("打电话");
    }
    public synchronized void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
    }
    public void normalFunc(){
        System.out.println("我是个普通方法");
    }

}

4.两个对象两个锁,执行顺序是 没有sleep的先执行,有的后执行(由于没有资源的竞争,按照正常情况执行)
//执行结果打电话 我是个普通方法 发短信,由于打电话比普通方法先执行,所以先调用
//线程与线程之间竞争(按谁先调用,谁先) 锁与锁之间的竞争(谁先拿到锁,谁先执行)

 public class eightLockProblems { //线程之间资源的竞争,而不是同一个对象锁的竞争
	
    public static void main(String[] args) throws InterruptedException {
        //与上面的区别是资源类是2个了,但是是相同的对象
        A1 a1 = new A1();
        A1 a2 = new A1();   
        new Thread(()->{//锁之间没有资源竞争,所以不用等另外一个锁,另外一个锁直接执行
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start(); //没有竞争

        new Thread(()->{a2.call();},"call").start();   //没有竞争
        new Thread(()->{a1.normalFunc();},"normal").start();
    }


}
class A1 {

    public synchronized void call(){

        System.out.println("打电话");
    }
    public synchronized void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
    }
    public void normalFunc(){
        System.out.println("我是个普通方法");
    }

}

5.静态同步方法,只有一个对象 执行顺序是 sleep方法后是另外一个, 因为static修饰是Class模板全局唯一,所以两个同步静态方法用的是同一把锁,所以安装顺序执行
6.静态同步方法,只有两个对象, 还是顺序执行(和5一样的执行结果,无论new多少个都是锁Class对象)
//运行结果 我是个普通方法 发短信 打电话

public class eightLockProblems1 {

    public static void main(String[] args) throws InterruptedException {
        A2 a1 = new A2();
        A2 a2 = new A2();
        new Thread(()->{//无论执行多少次都是普通方法,发短信先执行,因为他先拿到a1这个锁对象(这里锁的是Class模板)
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start();

        new Thread(()->{a2.call();},"call").start();
        new Thread(()->{a1.normalFunc();},"normal").start();
    }


}

class A2 {

    public static synchronized void call(){ //放在static区

        System.out.println("打电话");
    }
    public static synchronized void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
//      类模板全局唯一在JVM里面讲的  Class aClass = this.getClass();
    }
    public void normalFunc(){
        System.out.println("我是个普通方法");
    }

}

7.静态同步方法和普通同步方法,只有一个对象, 还是没有sleep先执行(代码如6)
8.静态同步方法和普通同步方法,只有两个对象, 还是没有sleep先执行(代码如6) (就还是Class竞争,谁先拿到,谁先执行,普通static不用锁竞争Class对象先执行)

//结果 : 我是个普通方法 发短信 我是个static同步方法(静态) 打电话(静态同步)

public class eightLockProblems1 {

    public static void main(String[] args) throws InterruptedException {
        A2 a1 = new A2();
        A2 a2 = new A2();
        new Thread(()->{//无论执行多少次都是发短信先执行,因为他先拿到a1这个锁对象(这里锁的是Class模板)
            try {
                a1.sendSMS();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"send").start();

        new Thread(()->{a2.call();},"call").start();
        new Thread(()->{a2.normalStaticFunc();},"normalstatic").start();//
        new Thread(()->{a1.normalFunc();},"normal").start();
    }


}

class A2 {

    public static synchronized void call(){

        System.out.println("打电话");
    }
    public static synchronized void sendSMS() throws InterruptedException {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("发短信");
//      类模板全局唯一在JVM  Class aClass = this.getClass();
    }
    public void normalFunc(){
        System.out.println("我是个普通方法");
    }

    public static synchronized void normalStaticFunc(){
        System.out.println("我是个static同步方法");
    }

}

你可能感兴趣的:(java,jvm)