第十二章 并发

线程

package chapter12_concurrent.threads;public class ThreadsTest {public static final int DELAY = 10;public static final int STEPS = 100;public static final double MAX_AMOUNT = 1000;public static void main(String[] args) {var bank = new Bank(4, 100000);//Runnalbe 是一个函数式接口,可以用一个lambda表达式创建一个实例Runnable task1 = () -> {try {for (int i = 0; i < STEPS; i++) {double amount = MAX_AMOUNT * Math.random();bank.transfer(0, 1, amount);Thread.sleep((long) (DELAY * Math.random()));}} catch (InterruptedException e) {}};Runnable task2 = () -> {try {for (int i = 0; i < STEPS; i++) {double amount = MAX_AMOUNT * Math.random();bank.transfer(2, 3, amount);//休眠制定的毫秒数Thread.sleep((long) ( DELAY * Math.random()));}} catch (InterruptedException e) {}};//构造一个Thread对象,启动线程new Thread(task1).start();new Thread(task2).start();}
}

线程状态

  • New, Runnable, Blocked, Waiting, Timed waiting, Terminated

分别表示线程的六种状态: 新建, 可运行, 阻塞, 等待, 计时等待, 终止


新建线程

  • new Thread(r) 新建线程, 但是还没有开始运行

可运行线程

  • 调用start方法后线程就属于可运行状态, 处于runnable可能运行也可能没有运行

阻塞和等待进程

  • 线程处于阻塞和等待状态不活动,不运行任何代码,消耗最少资源
  • 当线程试图获取一个内部的对象锁,而该锁目前被其他线程占有,该线程就会被阻塞.所有其他线程释放这个锁,并且线程调度器允许该线程持有这个锁,他将变成非阻塞状态
  • 当线程等待另一个线程通知调度器出现一个条件时,这个线程会进入等待状态
  • 有的方法有超时参数,调用这些方法会让线程进入计时等待状态.这一状态会一直等待到超时期满或者接收到适当的通知

终止线程

  • run方法正常退出
  • 一个没有捕获的异常终止了run方法

线程属性

中断线程

  • interrupt方法可以用来请求终止一个线程,程序调用该方法就会设置线程中断状态
  • 测试是否设置了中断状态:Thread.currentThread()获得当前线程
while(!Thread.currentThread().isInterrupted()){...
}
  • 线程被阻塞就无法检查中断状态

  • 当在一个被sleep, wait调用的阻塞的线程上调用interrupt方法,那个阻塞调用将被一个InterruptedException异常中断

  • 一般将中断解释为一个中止请求

  • 如果循环调用了sleep,不要检测中断状态,应当捕获InterruptedException

  • interrupted: 静态方法, 检查当前线程是否中断,并且清楚线程中断状态

  • isInterrupted: 实例方法, 检查是否有线程被中断,不改变中断状态

  • 不要抑制InterruptedException异常:

    • catch子句中调用Thread.currentThread().interrupt()设置中断状态,调用者就可以检查中断状态了

    • void mySubTask(){...try{sleep(delay);}catch(InterruptedException e){Thread.currentThread().interrupt()}
      }
      
    • 更好的是,标记方法,去掉try语句块

    • void mySubTask() throw InterruptedException
      {    ...   sleep(delay);
      }
      

守护线程

  • t.setDaemon(true);
  • 守护线程唯一作用就是为其他线程提供服务

线程名

  • 默认状态下有容易记忆的名字
  • 改名:setName(...)

未捕获异常的处理器

  • 线程组ThreadGroup类实现了Thread.UncaughtExceptionHandler接口,其uncaughtException方法执行以下操作:
    1. 该线程若有父线程那么调用父线程的uncaughtException方法
    2. 如果Thread.getDefaultExceptionHandler方法返回一个非null处理器,调用该处理器
    3. 否则,如果Throwable类是ThreadDeath的一个实例,什么也不做
    4. 否则将线程的名字和Throwable栈轨迹输出到System.err

线程的优先级

  • setPriority方法提高或者降低任何一个线程的优先级
  • MIN_PRIORITY(1), NORM_PRIORITY(5), MAX_PRIORITY(10)

同步

  • 竞态条件: 两个及以上线程共享对同一组数据的存取, 线程相互覆盖导致对象破坏
  • 不同步的操作:
package chapter12_concurrent.unsynch;public class UnsynchBankTest {public static final int NACCOUNT = 100;public static final double INITIAL_BALANCE = 1000;public static final double MAX_AMOUNT = 1000;public static final int DELAY = 10;public static void main(String[] args) {var bank = new Bank(NACCOUNT, INITIAL_BALANCE);for (int i = 0; i < NACCOUNT; i++) {int fromAccount = i;Runnable r = () -> {try {while (true) {int toAccount = (int) (bank.size() * Math.random());double amount = MAX_AMOUNT * Math.random();bank.transfer(fromAccount, toAccount, amount);Thread.sleep((int) (DELAY * Math.random()));}} catch (InterruptedException e) {}};var t = new Thread(r);t.start();}}
}

锁对象

  • 两种机制可以防止并发访问代码块: synchronized, ReentrantLock
  • 基本结构:
mylock.lock();
try{critical section
}
finally{myLock.unlock();
}
  • 该结构确保任何时刻只有一个线程进入临界区,一旦一个线程锁定了锁对象,其他任何线程无法通过lock语句
  • 要把unlock放入finally语句.如果临界区代码异常,锁必须释放,否则线程永远阻塞
public class bank{private ReentrantLock bankLock = new ReentrantLock();......public void transfer(int from, int to, double amount){bankLock.lock();try {if (accounts[from] < amount) return;System.out.print(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());}finally {bankLock.unlock();}}
}
  • 每个bank有自己的ReentrantLock对象,两个线程视图访问同一个bank对象,锁可以用来保证串行化访问
  • 两个线程访问不同的bank对象,每个线程会得到不同的锁对象,线程不会阻塞

条件对象

  • 下面的Bank类加入了锁对象, 保护金额转账不够时候线程覆盖的情况
  • 引入了条件对象, 调用await方法将当前线程暂停,放弃锁,允许其他线程执行
  • 另一个线程完成转账后调用signalAll重新激活等待这个条件的所有线程
  • 其中的某个线程将从await调用处返回得到这个锁,继续执行之前暂停的地方
package chapter12_concurrent.synch;import java.util.*;
import java.util.concurrent.locks.*;public class Bank {private final double[] accounts;private ReentrantLock banklock;private Condition sufficientFunds;public Bank(int n, double initialBalance) {accounts = new double[n];Arrays.fill(accounts, initialBalance);banklock = new ReentrantLock();sufficientFunds = banklock.newCondition();}public void transfer(int from, int to, double amount) throws InterruptedException{banklock.lock();try {while (accounts[from] < amount) {sufficientFunds.await();}System.out.println(Thread.currentThread());accounts[from] -= amount;System.out.printf(" %10.2f from %d to %d.", amount, from, to);accounts[to] += amount;System.out.printf(" Total balance: %10.2f%n", getTotalBanlance());sufficientFunds.signalAll();}finally {banklock.unlock();}}public double getTotalBanlance() {banklock.lock();try {double sum = 0.0;for (double a: accounts)sum += a;return sum;}finally {banklock.unlock();}}public int size() {return accounts.length;}
}

CoreJava 笔记总结-第十二章 并发-1相关推荐

  1. CoreJava 笔记总结-第十二章 并发-2

    文章目录 第十二章 并发 `synchronized`关键字 同步块 监视器概念 `volatile`字段 `final`变量 原子性 死锁 线程安全的集合 阻塞队列 映射条目的原子更新 对并发散列映 ...

  2. 李弘毅机器学习笔记:第十二章—Recipe of Deep Learning

    李弘毅机器学习笔记:第十二章-Recipe of Deep Learning 神经网络的表现 如何改进神经网络? 新的激活函数 梯度消失 怎么样去解决梯度消失? Adaptive Learning R ...

  3. 系统架构师学习笔记_第十二章_连载

    第十二章  系统安全架构设计 12.1  信息系统安全架构的简单描述 信息安全的特征 是为了保证信息的 机密性.完整性.可用性.可控性.不可抵赖性. 以风险策略为基础. 12.1.1  信息安全的现状 ...

  4. 《网络安全工程师笔记》 第十二章:域

    注:本笔记来自温晓飞老师的网络安全课程 第十二章:域 第一章:虚拟化架构与系统部署 第二章:IP地址详解 第三章:进制转换 第四章:DOS基本命令与批处理 第五章:用户与组管理 第六章:服务器远程管理 ...

  5. Boost 第十二章 并发编程

    本文章所有内容源于<BOOST程序库完全开发指南:深入C++"准"标准库(第3版)>第十二章 本章内容包括Boost库中的三个并发编程组件.atomic,它实现了C++ ...

  6. java 并发测试程序_java并发编程实战:第十二章---并发程序的测试

    并发程序中潜在错误的发生并不具有确定性,而是随机的. 安全性测试:通常会采用测试不变性条件的形式,即判断某个类的行为是否与其规范保持一致 活跃性测试:进展测试和无进展测试两方面,这些都是很难量化的(性 ...

  7. 深入理解计算机系统 第十二章 并发编程

    如果逻辑控制流在时间上重叠,那么它们就是并发的(concurrent) 这种常见的现象称为并发(concurrency),出现在计算机系统的许多不同层面上. 并发不仅仅局限于内核,它也可以在应用程序中 ...

  8. 组织行为学笔记:第十二章 组织结构和组织设计

    一.古典组织理论 任何一个单位都要处理诸如权力,责任,分工,专业化以及各部分之间相互依存,相互联系等基本要素. 工作分工 部门领导把自己单位的工作分成不同层次与职能,然后把人员,资源分配到划分成不同层 ...

  9. 【APUE笔记】第十二章 高级I/O

    文章目录 1.非阻塞I/O 2.记录锁 2.1.fcntl记录锁 2.2.锁的隐含继承和释放 2.3.建议性锁和强制性锁 3.流 3.1.流简介 3.2.流消息 3.3.putmsg和putpmsg函 ...

最新文章

  1. petalinux 下使用 xsa 查看所有的 Zynq Reg 设置
  2. CentOS6.5下通过yum仓库安装mysql
  3. 线程池配置合理线程数?
  4. 切割图形_重庆Q3245R锅炉板加工几何图形2021新闻
  5. javap分析字符串拼接执行流程
  6. c语言 static 关键字的作用
  7. EditText焦点问题
  8. 2021抖音私域经营白皮书
  9. 50 - 算法- LeetCode 104 -二叉树
  10. sequelize 外键关联_用Sequelize计算关联条目
  11. python如何生成excel文件夹_用python脚本通过excel生成文件夹树结构
  12. (大家发表一下看法)微软研发智能系统 可通过电脑24小时监控员工
  13. C/C++中类型变量转换之间的数值溢出
  14. Java、素数的个数
  15. TouchGFX如何校准电阻触摸屏
  16. 工商银行销售基金一览表
  17. 生成国庆头像网站的源码及搭建教程
  18. Spark快速大数据分析——Spark安装与IDEA 开发(贰)
  19. PAT(乙级) 1045 快速排序
  20. w ndows资源管理器无响应,windows资源管理器未响应

热门文章

  1. linux block设备,Linux I/O Block--块设备的表示
  2. 产品运行所需的信息检索失败_禁煤后用什么替代锅炉?看看三种热源运行费用对比就知道了...
  3. 如何才能避免聚会尬聊
  4. 最诡异数学悖论:1+1=1
  5. 您的屁股发热严重,请降温后使用。
  6. Python 写各大聊天系统的屏蔽脏话功能原理
  7. 搞笑动图:这些痛,只有程序员懂…
  8. sklearn线性回归详解
  9. mysql学时用什么类型_MYSQL数据库学习----MYSQL数据类型
  10. 华夫饼为什么不松软_掌握这2个关键点,5个小细节,3个小技巧,保证烙饼松软又好吃...