2019独角兽企业重金招聘Python工程师标准>>>

1.线程的通知与等待

Java中的Object类是所有类的父亲,鉴于继承机制,Java把所有类都需要的方法放到了Object类里面,其中就包含线程的通知与等待系列。

wait()方法

当一个线程调用一个共享变量的wait()方法时,该调用线程会被阻塞挂起,并释放该共享变量上的锁,直到下面几件事情之一才返回:

1)其他线程调用了该共享对象的notify()或者notifyAll()方法

2)其他线程调用了该线程的interrupt()方法,该线程抛出InterruptedException异常返回

另外需要注意的是调用共享变量的wait()方法前需要事先获取该对象的监视器锁,否则调用 wait()方法时调用线程会抛出IllegalMonitorStateException异常。

如何获取监视器锁?

a.执行synchronized同步代码块时,使用该共享变量作为参数

synchronized(共享变量) {// doSomething
}

b.调用该共享变量的方法,并且该方法使用了synchronized修饰

synchronized void add(int a, int b) {// doSomething
}

需要注意的是一个线程可以从阻塞挂起状态变为可运行状态(也就是被唤醒),即使该线程没有被其他线程调用notify()、notifyAll()方法进行通知,或者被中断,或者等待超时,这就是所谓的虚假唤醒。

防范虚假唤醒的一个方法就是在一个循环中调用wait()方法,退出循环的条件是满足了唤醒该线程的条件。

synchronized(obj) {while(条件不满足) {obj.wait();}
}

wait(long timeout)方法

与wait()方法的不同之处在于,如果一个线程调用共享对象的该方法挂起后,没有指定的timeout ms时间内被其他线程调用该共享变量的notify()或者notifyAll()方法唤醒,那么该函数还是会因为超时返回。

notify()方法

一个线程调用共享对象的notify()方法后,会唤醒一个在该变量上调用wait系列方法后被挂起的线程。一个共享变量上可能会有多个线程在等待,具体唤醒哪个等待的线程是随机的。

此外,被唤醒的线程不能马上从wait()方法返回并继续执行,它必须在获取了共享对象的监视器锁后才可以返回,也就是被唤醒的线程也不一定会获取到共享变量的监视器锁,这是因为该线程要和其他线程一起竞争该锁,只有竞争到了共享变量的监视器锁后才可以继续执行。

类似wait方法,只有当前线程获取到监视器锁后才可以调用notify()方法,否则会抛出IllegalMonitorStateException异常。

notifyAll()方法

与notify()方法的区别是,notify()会唤醒一个阻塞在该共享变量上的一个线程,notifyAll()方法则会唤醒所有在共享变量上的=由于被调用wait()方法而被挂起的线程。

一个生产者消费者的例子:

public class WaitNotifyTest3 {private static final Queue<String> queue = new LinkedBlockingQueue<>();private static final int MAX_SIZE = 1000;public static void main(String[] args) {Thread producer = new Thread(() -> {while (true) {synchronized (queue) {while(queue.size() == MAX_SIZE) {try {queue.wait();} catch(Exception ex) {ex.printStackTrace();}}queue.add("ele");queue.notify();}}});Thread consumer = new Thread(() -> {while (true) {synchronized (queue) {while(queue.size() == 0) {try {queue.wait();} catch(Exception ex) {ex.printStackTrace();}}System.out.println(queue.poll());queue.notify();}}});producer.start();consumer.start();}
}

2.等待线程执行终止

在项目实践中经常会遇到一个场景就是需要等待某几件事情完成后才能继续往下执行,比如多个线程加载资源,需要等待多个线程全部加载完毕再汇总处理。Thread类中有一个join方法提供该功能。

看一个栗子:

public class JoinTest {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("child threadOne over");});Thread thread2 = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}try {thread1.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("child threadTwo over");});thread1.start();thread2.start();System.out.println("wait all child thread over");thread1.join();thread2.join();System.out.println("all child thread over");}
}

另外线程A调用线程B的join方法后会被阻塞,当其他线程调用了线程A的interrupt()方法中断了线程A时,线程A会抛出InterruptedException异常而返回。如下:

public class JoinTest2 {public static void main(String[] args) {Thread thread1 = new Thread(() -> {System.out.println("thread1 begin run");for (; ; ) {}});final Thread threadMain = Thread.currentThread();Thread thread2 = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}threadMain.interrupt();});thread1.start();thread2.start();try {thread1.join();} catch (InterruptedException e) {e.printStackTrace();}}
}

注意这里调用的是主线程的interrupted方法。

转载于:https://my.oschina.net/hensemlee/blog/3003562

Java并发编程之美读书笔记-并发编程基础2相关推荐

  1. 编程之美 - 读书笔记 - 卖书折扣问题的贪心解法

    <编程之美>读书笔记(四):卖书折扣问题的贪心解法 每 次看完<编程之美>中的问题,想要亲自演算一下或深入思考的时候,都觉得时间过得很快,动辄一两个小时,如果再把代码敲一遍的话 ...

  2. 竞态条件的赋值_《Java并发编程实战》读书笔记一:基础知识

    一.线程安全性 一个对象是否是需要是线性安全的,取决于它是否需要被多个线程访问 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要额外的同步,这个 ...

  3. 【编程之美/读书笔记】Chapter 1 游戏之乐

    这里就不写每个问题的题目了,只是记录一下自己的总结和心得. 1.1 让CPU占用率听你指挥 这个题目我刚接触的想法是和多核多线程要扯上关系的,因为自己写个死循环只能跑到CPU 35%左右的占用率,但是 ...

  4. 编程之美读书笔记2.1—求二进制数中1的个数

    解法一: 可以举一个8位二进制的例子.对于二进制操纵,我们除以一个2,原来数字就会减少一个0(向右移一位).如果除的过程中有余,那么久表示当前位置有一个1. 以10100010为例: 第一次除以2时, ...

  5. 编程之美--读书笔记--返回一个数组中所有元素被第一个元素除的结果

    笔试题目1:写一个函数,返回一个数组中所有元素被第一个元素除的结果 很多人会想到如下: void DivAarry(int *pArray,int size) { for(int i=size-1;i ...

  6. 编程之美读书笔记之-高效率的安排见面会

    问题一: n个同学,分别对m个招聘见面会感兴趣.为了满足所有学生的要求,hr希望让每个同学都能参加自己所有感兴趣的见面会.然后每个见面会的时间为t.问如何安排见面会能够使得所有见面会总的时间最短. 建 ...

  7. 中国象棋将帅问题java_编程之美读书笔记1.2——中国象棋将帅问题

    http://blog.csdn.net/pipisorry/article/details/36380669 问题:下过中国象棋的朋友都知道,双方的"将"和"帅&quo ...

  8. 编程之美 - 读书笔记 - 烙饼问题与搜索树

    前 面已经写了一些关于烙饼问题的简单分析,但因为那天太累有些意犹未尽,今天再充实一些内容那这个问题研究透.我想,通过这篇文章,我们就可以把这一类问题 搞懂.再遇到优化问题,如果我们想不到别的办法,就可 ...

  9. 编程之美读书笔记_1.1_让CPU占用率曲线听你指挥

    题目:写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率.程序越精简越好,计算机语言不限.例如,可以实现下面三种情况:   1.    CPU的占用率固定在50 ...

最新文章

  1. linux定时任务案例,Linux定时任务案例
  2. 2.1 0/1分类问题-机器学习笔记-斯坦福吴恩达教授
  3. 【大话存储】学习笔记(7章), OSI模型
  4. 运营商市场经营方向及趋势
  5. coordinatorlayout_一篇文章学会Coordinatorlayout+AppbarLayout
  6. C#经典系列-键值对
  7. 资源放送丨《PostgreSQL中的锁》PPT视频
  8. java零碎要点---Tesseract 3.0,Java OCR 图像智能字符识别技术,可识别中文
  9. java nginx 重启吗_Nginx的启动、停止、平滑重启
  10. PAIP.ecshop file_put_contents Warning notice解决方法
  11. 2021-05-19 C语言逻辑取反! 学习
  12. word中的左拐箭头和向下箭头的差别
  13. U盘装win2012R2,win2016,win2019等超过4G安装盘的系统
  14. 什么是三网合一短信接口呢
  15. 历年软考网络规划师考点总结
  16. [音乐]阿桑的《叶子》
  17. QuickBI 使用记录
  18. Dilate Gated Convolutional Neural Network
  19. uniapp连接低功耗打印机实例,
  20. 网页中怎样在线播放音乐和视频

热门文章

  1. linux怎么运行cli,linux脚本 直接用cli模式运行脚本
  2. 如何解决线程安全的问题
  3. html mint ui,vue mint-ui初次使用总结
  4. java越权发送邮件_已登录用户 越权 访问action方法怎么解决?
  5. 如何用pip指令将python包安装到虚拟环境中
  6. c语言入口及出口参数说明,麻烦帮忙指出一下这个函数的入口参数和出口参数呀!...
  7. case when的判断顺序_CASE 表达式
  8. 2021-01-27 CentOS系统将UTC时间修改为CST时间方法
  9. 华为手机助手解析包时出现问题_iOS12.0-12.1.2设备降级/平刷iOS12.0-12.1.2教程(付问题解决)...
  10. itextpdf添加表格元素_使用iText填充pdf表单