干货来袭:图解Java多线程(八)

开课吧开课吧锤锤2021-03-16 09:59

    Java编程语言是一种简单、面向对象、分布式、解释型、健壮安全、与系统无关、可移植、高性能、多线程和动态的语言。如今Java已经广泛应用于各个领域的编程开发。

    线程通信

    wait+notify

    线程间通信可以通过共享变量+wait()&notify()来实现

    wait()将线程进入阻塞状态,notify()将线程唤醒

    当多线程竞争访问对象的同步方法时,锁对象会关联一个底层的Monitor对象(重量级锁的实现)

    如下图所示Thread0,1先竞争到锁执行了代码后,2,3,4,5线程同时来执行临界区的代码,开始竞争锁

Java

    1、Thread-0先获取到对象的锁,关联到monitor的owner,同步代码块内调用了锁对象的wait()方法,调用后会进入waitSet等待,Thread-1同样如此,此时Thread-0的状态为Waitting

    2、Thread2、3、4、5同时竞争,2获取到锁后,关联了monitor的owner,3、4、5只能进入EntryList中等待,此时2线程状态为Runnable,3、4、5状态为Blocked

    3、2执行后,唤醒entryList中的线程,3、4、5进行竞争锁,获取到的线程即会关联monitor的owner

   4、 3、4、5线程在执行过程中,调用了锁对象的notify()或notifyAll()时,会唤醒waitSet的线程,唤醒的线程进入entryList等待重新竞争锁

    注意:

    1、Blocked状态和Waitting状态都是阻塞状态

    2、Blocked线程会在owner线程释放锁时唤醒

    3、wait和notify使用场景是必须要有同步,且必须获得对象的锁才能调用,使用锁对象去调用,否则会抛异常

    wait()释放锁进入waitSet可传入时间,如果指定时间内未被唤醒则自动唤醒

    notify()随机唤醒一个waitSet里的线程

    notifyAll()唤醒waitSet中所有的线程

    staticfinalObjectlock=newObject();

    newThread(()->{

    synchronized(lock){

    log.info("开始执行");

    try{

    //同步代码内部才能调用

    lock.wait();

    }catch(InterruptedExceptione){

    e.printStackTrace();

    }

    log.info("继续执行核心逻辑");

    }

    },"t1").start();

    newThread(()->{

    synchronized(lock){

    log.info("开始执行");

    try{

    lock.wait();

    }catch(InterruptedExceptione){

    e.printStackTrace();

    }

    log.info("继续执行核心逻辑");

    }

    },"t2").start();

    try{

    Thread.sleep(2000);

    }catch(InterruptedExceptione){

    e.printStackTrace();

    }

    log.info("开始唤醒");

    synchronized(lock){

    //同步代码内部才能调用

    lock.notifyAll();

    }

    //执行结果

    14:29:47.138[t1]INFOTestWaitNotify-开始执行

    14:29:47.141[t2]INFOTestWaitNotify-开始执行

    14:29:49.136[main]INFOTestWaitNotify-开始唤醒

    14:29:49.136[t2]INFOTestWaitNotify-继续执行核心逻辑

    14:29:49.136[t1]INFOTestWaitNotify-继续执行核心逻辑

    wait和sleep的区别?

    二者都会让线程进入阻塞状态,有以下区别

    1、wait是Object的方法sleep是Thread的方法

    2、wait会立即释放锁sleep不会释放锁

    3、wait后线程的状态是Wattingsleep后线程的状态为Time_Waiting

    park&unpark

    LockSupport是juc下的工具类,提供了park和unpark方法,可以实现线程通信

    与wait和notity相比的不同点

    1、wait和notify需要获取对象锁parkunpark不要

    2、unpark可以指定唤醒线程notify随机唤醒

    3、park和unpark的顺序可以先unparkwait和notify的顺序不能颠倒

    以上内容由开课吧老师猿小布提供,更多Java教程尽在开课吧广场Java教程频道。

有用
分享