大家好,欢迎来到IT知识分享网。
目录
复习一下5:30:
(20条消息) java释放线程资源_Java线程之释放锁,释放资源,释放CPU_瓦克五的博客-CSDN博客
举个例子:就跟你去酒店一样在大堂找老总解决排队问题,你一直在大堂找老总就会影响其他客人,所以酒店给你安排到贵宾室等待,直到老总来了,在大堂,事情得到解决,重新在酒店外排队候单;
WAITTING和BLOCKED区别
waitting:是线程已经获取了锁,但又放弃了锁(有些问题需要解决)——>进入了waitset(在Monitor中)进行等待;——>唤醒:Owner调用notify()或notifyAll()方法进行唤醒——>唤醒后线程继续进入EntryList进行等待;
目的:释放锁,自己在休息室等待,将锁资源让给其他线程;
只有线程成为了Owner才有机会调用wait()方法与notify();
BLOCKED:线程没有获取锁,线程在EntryList中进行等待;——>唤醒:Owner清空,则其他线程有机会;
共同点:都阻塞了;
wait和sleep的区别
sleep:是Thread线程的方法,不需要强制在synchronized代码块中使用,并且在使用sleep睡眠的同时,锁对象是不会释放的;
wait:需要强制在synchronized中使用,因为他是拥有锁资(前提条件)源然后再放弃锁资源的,并且它是属于Object中的方法,使用wait()的时候,会释放锁资源;
例子:
package com.example.juc.WAndN; import lombok.extern.slf4j.Slf4j; / * @author diao 2022/4/9 */ @Slf4j(topic = "s.test02") public class test02 { //1.锁资源 static final Object lock=new Object(); public static void main(String[] args) throws InterruptedException { new Thread(()->{ synchronized (lock){ log.debug("获得锁"); try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } } },"t1").start(); //主线程睡1s,此时t1线程还在睡,看主线程是否能拿到lock对象资源 Thread.sleep(10000); //或发现10s拿不到,因为此时lock还在t1中,20s后即可 synchronized (lock){ log.debug("主线程拿到锁资源"); } } }
20s后主线程拿到锁资源,而不是10s,20s后因为锁来进行竞争,所以偏向锁变为轻量型锁;
如果是wait()的方法调用:
wait方法优化例子
利用sleep()方法缺点:不会释放锁资源,在小南线程等待的时候,其余线程拿不到锁资源不工作,直到送完烟,2s之后把锁资源释放了,其余线程才能工作;
缺点:
利用wait和notify优化:
package com.example.juc.WAndN; import lombok.extern.slf4j.Slf4j; import static java.lang.Thread.sleep; / * @author diao 2022/4/9 */ @Slf4j(topic = "c.TestCorrectPosture") public class TestCorrectPosture { //1.锁资源与条件判断 static final Object lock=new Object(); static boolean hasCigarette=false; public static void main(String[] args) throws InterruptedException { new Thread(()->{ /2. * 是否有烟的线程进行判断:若没有则不工作 */ synchronized (lock){ log.debug("有烟没?[{}]",hasCigarette); if(!hasCigarette){ log.debug("没烟,那就休息一会"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("有烟没?[{}]",hasCigarette); if(hasCigarette){ log.debug("我可以去干活了"); } } },"小南").start(); / * 其他工作线程 */ for (int i = 0; i < 5; i++) { new Thread(()->{ //等待小南释放锁资源 synchronized (lock){ log.debug("可以去干活了"); } },"其他人").start(); } / * 送烟线程 */ sleep(1000); new Thread(()->{ synchronized (lock){ //送烟 hasCigarette=true; log.debug("烟送到了哦"); //唤醒等待线程,相当于给等待的线程敲了下门说东西到了 lock.notify(); } },"小明").start(); } }
当有两个判断线程时,对notify的用法
wait的操作的办法:
写个循环,如果条件不对就一直等待
至于唤醒的线程,最好使用notifyAll()方法,否则会出现虚假唤醒:也就是说如果有两个线程要唤醒,你用notify的话就只会随机唤醒一个
package com.example.juc.WAndN; import lombok.extern.slf4j.Slf4j; import static java.lang.Thread.sleep; / * @author diao 2022/4/9 */ @Slf4j(topic = "c.TestCorrectPosture") public class TestCorrectPosture2 { //1.锁资源与判断 static final Object lock=new Object(); static boolean hasCigarette=false; static boolean hasEat=false; public static void main(String[] args) throws InterruptedException { / * 抽烟才能干活线程 */ new Thread(()->{ synchronized (lock){ log.debug("有烟没?[{}]",hasCigarette); //2进入判断 while(!hasCigarette){ log.debug("没烟,先歇会"); //3继续等待 try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //4有烟了 log.debug("有烟没?[{}]",hasCigarette); if(hasCigarette){ log.debug("可以开始干活了"); }else{ log.debug("没干成活"); } } },"小南").start(); new Thread(()->{ synchronized (lock){ log.debug("外卖到了吗?[{}]",hasEat); while(!hasEat){ log.debug("没到,继续摆烂"); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("外卖到了吗?[{}]",hasEat); log.debug("到了,开始干饭"); } },"小美").start(); / * 先让主线程先休息一下,让上面两个先执行,问有没有烟和有没有外卖 * 直到全部wait */ sleep(1000); new Thread(()->{ synchronized (lock){ hasEat=true; log.debug("外面到了哦!"); lock.notify(); } },"外卖小哥").start(); } }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/137310.html