当前位置: 首页 > news >正文

设计建设网站公司网站外贸怎么建立自己的网站

设计建设网站公司网站,外贸怎么建立自己的网站,如何做psd的模板下载网站,北京市顺义区住房和建设委员会网站1、为什么需要线程的等待和唤醒 线程的等待唤醒机制是一种经典的“生产者和消费者”模型。例如食品加工厂,食品加工人员和原料补给人员,在有充足原料时,补给人员是在等待,等到原料不够时,食品加工人员通知补给人员&am…

1、为什么需要线程的等待和唤醒

线程的等待唤醒机制是一种经典的“生产者和消费者”模型。例如食品加工厂,食品加工人员和原料补给人员,在有充足原料时,补给人员是在等待,等到原料不够时,食品加工人员通知补给人员(唤醒)。在我们开发诸如此类需求的时候两个线程之间协调等待和唤醒还是很有必要的。那咱们看看都有那些方式实现线程等待和唤醒机制。

2、线程等待和唤醒机制方式 

实现线程等待和唤醒机制主要有3中方式分别是:

  • 使用 Object 中的 wait() 方法让线程等待,使用 Object 中的 notify() 方法唤醒线程
  • 使用 JUC 包中 Condition 的 await() 方法让线程等待,使用 signal() 方法唤醒线程
  • 使用LockSupport类的park()方法让线程等待,使用unpark()方法唤醒线程。 

 那这三种方式具体怎么使用,都有那些优缺点呢?我们通过实例代码演示。

3、线程等待和唤醒机制实例

3.1、使用 Object 中的 wait() 方法让线程等待,使用 Object 中的 notify() 方法唤醒线程

代码:

package com.lc.test02;import java.util.concurrent.TimeUnit;/*** @author liuchao* @date 2023/4/8*/
public class ThreadWaitOne {/*** 注意:必须使用同一把锁*/static Object lock = new Object();public static void main(String[] args) {/*** 线程1*/Thread t1 = new Thread(() -> {synchronized (lock) {System.out.println("进入" + Thread.currentThread().getName());try {lock.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println(Thread.currentThread().getName() + "被唤醒");}}, "t1");t1.start();try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();}/*** 线程2*/Thread t2 = new Thread(() -> {synchronized (lock) {System.out.println("进入" + Thread.currentThread().getName());lock.notify();System.out.println("唤醒通知已发");}}, "t2");t2.start();}
}

效果:

进入t1
进入t2
唤醒通知已发
t1被唤醒 

总结:此种方式必须使用同一把锁并且必须包含在synchronized代码块中,如果未使用synchronized包裹,则会报错。

Exception in thread "t1" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.lc.test02.ThreadWaitOne.lambda$main$0(ThreadWaitOne.java:24)
    at java.lang.Thread.run(Thread.java:750)

并且wait方法的调用必须要在notify/notifyAll的调用之前,否则线程将永远不会被唤醒。 

3.2、使用 JUC 包中 Condition 的 await() 方法让线程等待,使用 signal() 方法唤醒线程

代码:

package com.lc.test02;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @author liuchao* @date 2023/4/8*/
public class ThreadWaitTwo {/*** 必须是同一把锁*/static Lock lock = new ReentrantLock();static Condition condition = lock.newCondition();public static void main(String[] args) {/*** 线程1*/Thread t1 = new Thread(() -> {lock.lock();try {System.out.println("进入" + Thread.currentThread().getName());condition.await();} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}System.out.println(Thread.currentThread().getName() + "被唤醒");}, "t1");t1.start();try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();}/*** 线程2*/Thread t2 = new Thread(() -> {lock.lock();try {System.out.println("进入" + Thread.currentThread().getName());condition.signal();System.out.println("唤醒通知已发");} finally {lock.unlock();}}, "t2");t2.start();}
}

效果:

进入t1
进入t2
唤醒通知已发
t1被唤醒 

总结:使用此中方式必须配合lock,代码必须被lock包裹,否则将报错

Exception in thread "t1" java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2036)
    at com.lc.test02.ThreadWaitTwo.lambda$main$0(ThreadWaitTwo.java:28)
    at java.lang.Thread.run(Thread.java:750) 

 并且await方法的调用必须在signal/signalAll方法调用之前,否则t1也是不会被唤醒

3.3、使用LockSupport类的park()方法让线程等待,使用unpark()方法唤醒线程。  

LockSupport 类使用了一种名为 Permit (许可)的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可(permit),permit 只有两个值 1 和 0,默认是 0

  • 阻塞

        ①、park()/park(Object blocker)
        ②、permit 默认是 0,所以一开始调用 park() 方法,当前线程就会阻塞,直到别的线程将当前线程的 permit 设置为 1 时,park 方法会被唤醒,然后会将 permit 再次设置为 0 并返回。
        ③、阻塞当前线程/阻塞传入的具体线程

  • 唤醒

        ①、unpark(Thread thread)
        ②、调用 unpark(Thread thread) 方法后,就会将 thread 线程的许可 permit 设置为 1(注意多次调用 unpark 方法,不会累加,permit 值还是 1)会自动唤醒 thread 线程,即之前阻塞中的 LockSupport.park()方法会立即返回
        ③、唤醒处于阻塞状态的指定线程

代码:

package com.lc.test02;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;/*** @author liuchao* @date 2023/4/8*/
public class ThreadWaitThree {public static void main(String[] args) {/*** 线程1*/Thread t1 = new Thread(() -> {System.out.println("进入" + Thread.currentThread().getName());LockSupport.park();System.out.println(Thread.currentThread().getName() + "被唤醒");}, "t1");t1.start();try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();}/*** 线程2*/Thread t2 = new Thread(() -> {System.out.println("进入" + Thread.currentThread().getName());LockSupport.unpark(t1);System.out.println("唤醒通知已发");}, "t2");t2.start();}
}

效果:

进入t1
进入t2
唤醒通知已发
t1被唤醒 

结论:此种方式不需要增加同步机制,天生就是无锁机制实现线程等待和唤醒,并且因为是通过许可方式来唤醒线程的,所以许可是在等待(调用park()方法)前还是后是不影响的(park和unpark调用先后顺序我关),此种方式也是我们推荐使用的方式。当然,这种方式也是有缺点的,许可最多只有一个,如果等待多次(调用多次park()方法),线程也就永远不能唤醒了。

演示线程的唤醒和unpark先调用还是后调用无关:

package com.lc.test02;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;/*** @author liuchao* @date 2023/4/8*/
public class ThreadWaitThree {public static void main(String[] args) {/*** 线程1*/Thread t1 = new Thread(() -> {try {//等待300毫秒,让t2先执行TimeUnit.MILLISECONDS.sleep(300);} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("进入" + Thread.currentThread().getName());LockSupport.park();System.out.println(Thread.currentThread().getName() + "被唤醒");}, "t1");t1.start();/*** 线程2*/Thread t2 = new Thread(() -> {System.out.println("进入" + Thread.currentThread().getName());LockSupport.unpark(t1);System.out.println("唤醒通知已发");}, "t2");t2.start();}
}

效果:

进入t2
唤醒通知已发
进入t1
t1被唤醒 

演示多次调用unpark+多次调用park导致线程不能被唤醒:

package com.lc.test02;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;/*** @author liuchao* @date 2023/4/8*/
public class ThreadWaitThree {public static void main(String[] args) {/*** 线程1*/Thread t1 = new Thread(() -> {System.out.println("进入" + Thread.currentThread().getName());/*** 调用两次park方法*/LockSupport.park();LockSupport.park();System.out.println(Thread.currentThread().getName() + "被唤醒");}, "t1");t1.start();try {//等待300毫秒,让t2先执行TimeUnit.MILLISECONDS.sleep(300);} catch (InterruptedException e) {Thread.currentThread().interrupt();}/*** 线程2*/Thread t2 = new Thread(() -> {System.out.println("进入" + Thread.currentThread().getName());/*** 调用了两次park我们调用三次unpark 还是无法唤醒t1线程的*/LockSupport.unpark(t1);LockSupport.unpark(t1);LockSupport.unpark(t1);System.out.println("唤醒通知已发");}, "t2");t2.start();}
}

 

http://www.ds6.com.cn/news/84149.html

相关文章:

  • 天津做网站印标跟我学seo
  • 公司有域名的怎么建设网站网站seo快速
  • 山西建设工程协会网站微博热搜榜排名今日
  • 地方门户信息网站建设方案爱采购seo
  • php网页设计论文好搜网惠州seo
  • wordpress 博客分页如何优化seo技巧
  • 建设网站需要哪些设备前端性能优化有哪些方法
  • 大连网站建设怎么做重庆网站seo推广公司
  • 房地产做网站怎样吸引客户网络优化公司
  • 永康营销型网站建设seo营销工具
  • 免费网站建设方案短视频seo系统
  • 青浦网站制作口碑营销ppt
  • 网站关键词基础排名怎么做国际军事形势最新消息
  • 互联网三网合一网站建设seo专员简历
  • 丽水网站建设费用2023年5月疫情爆发
  • wordpress 插件报错百度seo快速排名优化
  • 如何给网站做下载附件seo 适合哪些行业
  • 装修效果图软件app哪个好灰色行业seo大神
  • 网站建设内容网站如何优化流程
  • 网站的站内结构锚文本是如何做的北京网站制作推广
  • dedecms做企业网站厦门seo代运营
  • 栾城seo整站排名计算机培训班
  • 网站怎么做发送邮件的超链接我想做网络推广
  • 廊坊做网站公司学网络营销
  • 石狮网站定制湖南seo优化推荐
  • 河南省住房和城乡建设厅新网站外链推广软件
  • 资质升级业绩备案在哪个网站做b2b网站大全
  • 怎么做网上卖菜网站短视频搜索seo
  • 织梦cms网站模板网站统计数据分析
  • 电影网站源码系统搜狗搜索网