java_JUC

什么是JUC

在这里插入图片描述
java.util 工具包
包:为了分类

业务:普通的线程 Thread
Runnable 没有返回值,效率相比入Callable 相对较低!,在企业级开发中用的相对较少!
在这里插入图片描述

在这里插入图片描述

2.线程和进程

线程,进程,如果不能使用一句话说出来的技术,不扎实

进程:一个程序,比如QQ.EXE,Music.exe, 程序的集合 .jar
一个进程往往可以包含多个线程,至少包含一个!
java 默认有几个线程? 2 个,main线程,GC 线程
线程:开了一个进程Typora,写字,自动保存(线程负责的)
对于 java 而言:Thread ,Runnable ,Callable
java 可以开启线程吗?
开不了的,调用的是底层的C++,java 无法操作硬件,他是运行在虚拟机上的

  public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

并发,并行

并发编程:并发,并行
并发(多线程操作同一资源)

  1. CPU一核,莫里出来多条线程,天下武功,为快不破,快速交替
    并行(多个人一起行走)
    2.CPU 多核,多个线程可以同时执行:要获取最好性能那么就要获取线程池。

package com.kuang.thread;
public class Test1 {

    public static void main(String[] args) {
        //获取CPU 的核数
        //CPU 密集型,IO 密集型
        System.out.println(Runtime.getRuntime().availableProcessors());
    }
}

并发编程的本质:充分利用CPU 的资源
所有的公司都很看重!
企业,挣钱,=>提高效率,裁员,找一个厉害的人,顶替三个不怎么样样的人;

线程有几个状态
6 种状态
//赋值线程状态
Thread.State state = Thread.State.NEW;

 public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
         //新生
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
         //运行
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
         //阻塞
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
         //等待,死死的等
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
         //超时等待
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        //终止
        TERMINATED;
    }


wait/sleep 区别

1. 来自不同的类
wait => Object
sleep =>Thread

2. 关于锁的释放
wait 会释放锁,sleep 睡觉了,抱着锁睡觉,不会释放!

3.使用的方位是不同的
wait wait必须在同步代码块中

sleep 可以再任何地方睡,

4.是否需要捕获异常
wait 需要是捕获异常 中断异常
sleep 必须要捕获异常

3.Lock 锁(重点)

传统 Synchronized

普通的多线程实现方式

package com.kuang;


/**
 * 普通的多线程实现方式
 */
public class SaleTicketDemo02 {
    /**
     * 接口实现
     * @param args
     */
    public static void main(String[] args) {
        new Thread(new B()).start();
    }
}

/**
 * class B 接口实现Runnable 接口
 */
class  B implements Runnable{

    @Override
    public void run() {
        System.out.println("test 类");
    }
}
输出结果:
test 类

正常公司使用的多线程:

package com.kuang;


//基本的卖票例子

/**
 * 真正的多线程开发,公司中的开发,降低耦合性
 * 线程就是一个单独的资源类,没有任何附属的操作!
 * 1.属性,方法
 */
public class SaleTicketDemo01 {


    public static void main(String[] args) {
        //并发:多线程操作同一个资源类,把资源类丢入线程
        Ticket ticket = new Ticket();

        //@FunctionInterface 函数式接口, jdk1.8 lambda 表达式(参数)->{代码}

        //并发: 多线程操作一个资源类,三个线程操作同一资源
        new Thread(()->{
            for (int i = 0; i <60 ; i++) {
                ticket.sale();
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i <60 ; i++) {
                ticket.sale();
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i <60 ; i++) {
                ticket.sale();
            }
        },"C").start();


    }
}

// 资源类 OOP编程
class Ticket{

   //属性,方法
   private int number =30;

    //卖票的方式
    // synchronized 本质:队列,锁
    //锁是锁对象,和Class 
    public synchronized void sale(){
        if(number>0){
            System.out.println(Thread.currentThread().getName()+"卖出了第"+number--+"票,剩余"+number);

        }
    }
    
}

输出结果:
A卖出了第30票,剩余29
B卖出了第29票,剩余28
B卖出了第28票,剩余27
B卖出了第27票,剩余26
B卖出了第26票,剩余25
B卖出了第25票,剩余24
B卖出了第24票,剩余23
B卖出了第23票,剩余22
B卖出了第22票,剩余21
B卖出了第21票,剩余20
B卖出了第20票,剩余19
B卖出了第19票,剩余18
B卖出了第18票,剩余17
B卖出了第17票,剩余16
B卖出了第16票,剩余15
B卖出了第15票,剩余14
B卖出了第14票,剩余13
B卖出了第13票,剩余12
B卖出了第12票,剩余11
B卖出了第11票,剩余10
B卖出了第10票,剩余9
B卖出了第9票,剩余8
B卖出了第8票,剩余7
B卖出了第7票,剩余6
B卖出了第6票,剩余5
B卖出了第5票,剩余4
B卖出了第4票,剩余3
B卖出了第3票,剩余2
B卖出了第2票,剩余1
B卖出了第1票,剩余0

如学生打饭排队,一对一服务,需要排队一个一个来,不然一起上前很混乱,如图:
在这里插入图片描述

LOCK 加锁跟解锁

在这里插入图片描述

在这里插入图片描述
公平锁:十分公平: 可以先来后到
非公平锁:十分不公平:可以插队(默认) 假如一个进程3s ,一个进程3h ,那可肯定先执行3s 的。

synchronized 全自动的,Ticket 手动的

下面是Lock 上锁

package com.kuang;


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

public class SaleTicketDemo03 {


    public static void main(String[] args) {
        //并发:多线程操作同一个资源类,把资源类丢入线程
        Ticket ticket = new Ticket();

        //@FunctionInterface 函数式接口, jdk1.8 lambda 表达式(参数)->{代码}

        //并发: 多线程操作一个资源类,三个线程操作同一资源
        new Thread(()->{ for (int i = 0; i <60 ; i++) ticket.sale();},"A").start();
        new Thread(()->{ for (int i = 0; i <60 ; i++) ticket.sale();},"B").start();
        new Thread(()->{ for (int i = 0; i <60 ; i++) ticket.sale();},"C").start();


    }
}

// Lock 锁 三部曲
//1.new ReentrantLock();
//2.lock.lock()加锁
//3.finally=>lock.unlock();解锁
class Ticket2{

    //属性,方法
    private int number =50;

    //可重入锁
    Lock lock = new ReentrantLock();

    //卖票的方式
    public  void sale(){
        lock.lock(); //加锁
        try {
            //业务代码
            if(number>0){
                System.out.println(Thread.currentThread().getName()+"卖出了第"+number--+"票,剩余"+number);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); //解锁
        }
    }
}

Lock 锁与Sycronized 有什么区别了。

  1. Synchronized 是内置的java 关键字,Lock 是一个类
  2. Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到锁
  3. Synchronized 会自动释放锁(a线程执行完会释放锁, b线程即使抛出异常也会释放锁 ),Lock 必须要手动会释放!,如果不释放锁,会死锁
  4. Synchronized 线程1(获得锁,阻塞),线程2(等待,傻傻的等);Lock 锁就不一定会等下下去了( lock.tryLock();//尝试获取锁)
  5. Synchronized 可重入锁,不可能中断的,非公平;Lock 可重入锁,可以中断锁(lock.unlock();),默认非公平(可以自己设置)
  6. Synchronized 适合锁少量的代码同步问题,Lock 适合锁大量的代码同步!

锁是什么,如何判断锁的是谁!
//Synchronized 锁的对象是方法的调用者
现在sleep 都这么调用:
TimeUnit.SECONDS.sleep(1);

生产者和消费者问题

面试:单例模式,排序算法,生产者和消费者,死锁
Synchronized wait notify 老版
juc lock 新版的

生产者和消费者问题Synchronized 版

package com;

/**
* 线程之间的通信问题:生产者和消费者问题! 等待唤醒, 通知唤醒
* 线程交替执行 A  B 操作同一个变量 num =0
* A num +1
* B num -1
*/
public class A {

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


}

// 判断等待,业务,通知
class Data { //数字 资源类
   private int number = 0;

   //+1
   public synchronized void increment() throws InterruptedException {
       if (number != 0) {
           //等待操作
           this.wait();
       }
       number++;
       System.out.println(Thread.currentThread().getName() + "=>" + number);
       //通知其他线程,我+1 完毕了
       this.notifyAll();//唤醒
   }

   //-1
   public synchronized void decrement() throws InterruptedException {
       if (number == 0) {
           //等待
           this.wait();
       }
       number--;
       System.out.println(Thread.currentThread().getName() + "=>" + number);
       // 通知其他线程,我-1 完毕了
       this.notifyAll();//唤醒
  }
}

问题存在,A,B,C,D 线程 !虚假唤醒
在这里插入图片描述
if 改为 while 判断,如果用if 会有虚假唤醒(if 不会停,就继续往下走),会输出number =2 ,用while 将正确输出结果,所以要用while 防止虚假唤醒。

代码如下:

package com;

/**
 * 线程之间的通信问题:生产者和消费者问题! 等待唤醒, 通知唤醒
 * 线程交替执行 A  B 操作同一个变量 num =0
 * A num +1
 * B num -1
 */
public class A {

    public static void main(String[] args) {
        Data data = new Data();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }


}

// 判断等待,业务,通知
class Data { //数字 资源类
    private int number = 0;

    //+1
    public synchronized void increment() throws InterruptedException {
        while (number != 0) {
            //等待操作  
            System.out.println(Thread.currentThread().getName() + "wait=>" + number);
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        //通知其他线程,我+1 完毕了
        this.notifyAll();//唤醒
    }

    //-1
    public synchronized void decrement() throws InterruptedException {
        while (number == 0) {
      	 //等待操作
            System.out.println(Thread.currentThread().getName() + "wait=>" + number);
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        // 通知其他线程,我-1 完毕了
        this.notifyAll();//唤醒
    }


}

输出结果:
A=>1
Await=>1
B=>0
Bwait=>0
A=>1
Await=>1
B=>0
Bwait=>0
A=>1
Await=>1
B=>0
Bwait=>0
C=>1
Cwait=>1
B=>0
Bwait=>0
A=>1
Await=>1
B=>0
Bwait=>0
C=>1
Cwait=>1
B=>0
Bwait=>0
D=>1
Dwait=>1
Await=>1
B=>0
Bwait=>0
C=>1
Cwait=>1
B=>0
Bwait=>0
A=>1
Await=>1
Dwait=>1
B=>0
Bwait=>0
C=>1
Cwait=>1
B=>0
D=>1
Dwait=>1
Await=>1
Cwait=>1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值