[温故]图解java多线程设计模式(一)
去年看完的《图解java多线程设计模式》,可惜当时没做笔记,导致后来忘了许多东西,打算再温习下这本书,顺便在这里记录一下~
一、顺序执行、并行、并发
顺序执行:多个操作按照顺序依次执行。
并行:多个任务同时进行,同一时间内可以执行多个任务,这种方式,叫做并行执行,比如多核处理器,多个核可以同时处理多个任务。
并发:多个任务通过切分时间段,来达到“同时进行”的效果,比如单核处理器,在“同时”处理多个任务时,就会不停的切换来执行不同的任务,不可能有同一时间执行不同任务的情况。
下面引用别人的一句话来说明下并行和并发:
并发是两个任务可以在重叠的时间段内启动,运行和完成。并行是任务在同一时间运行,例如,在多核处理器上。 并发是独立执行过程的组合,而并行是同时执行(可能相关的)计算。 并发是一次处理很多事情,并行是同时做很多事情。
应用程序可以是并发的,但不是并行的,这意味着它可以同时处理多个任务,但是没有两个任务在同一时刻执行。
应用程序可以是并行的,但不是并发的,这意味着它同时处理多核CPU中的任务的多个子任务。
一个应用程序可以即不是并行的,也不是并发的,这意味着它一次一个地处理所有任务。
应用程序可以即是并行的也是并发的,这意味着它同时在多核CPU中同时处理多个任务。
二、synchronized修饰符
当我们说一个线程获得锁以后,则意味着这个线程可以执行当前对象(或类)里的synchronized方法,而且他线程则需要排队等待该线程释放锁以后才可能获得锁,进而执行锁里面的程序。
synchronized修饰后,存在对象锁和类锁两种类型。
2.1:对象锁
synchronized (this){
...略
}
2.2:类锁
synchronized (XXX.class){
...略
}
2.3:区别和作用域
对象锁指的是当前线程获得了某个实例的锁,假如有个Word类,有A、B两个同步方法,C属于普通方法,如图所示:

图1
可以发现,对象锁的作用域只针对当前对象生效,就像w1和w2里的A方法可以被不同的线程同时执行,但是同一个对象内的同步块,却只允许持有当前对象锁的线程执行,如t2、t3均被挡在了外面,当t1释放锁以后,t2、t3才会重新竞争锁,竞争到锁以后就会执行自己想要执行的同步逻辑。
类锁指的是当前线程获得了某个类的锁,还是Word类,有A、B两个static方法(静态方法属于类方法,加synchronized修饰符后等效于上面提到的synchronized(Word.class)),C属于普通static方法,如图所示:

图2
跟上面相比较,这里的t5受到了t1的影响,因为t1获得了Word类的锁,w1和w2共属一个类,因此t1获得类锁以后,其他线程想要访问这个类里的同步块,就得等到t1释放锁以后才可以继续竞争锁然后执行自己想要执行的同步逻辑。
三、线程间的通信
3.1:Wait
这几个方法是属于每个实例对象的,所有实例都拥有一个“等待队列”(虚拟概念,实例里并不存在该字段),它是在实例的wait方法调用后存放停止操作线程的队列。执行wait方法后,线程进入当前实例的“等待队列”,以下几种情况可以让线程退出“等待队列”:
①其他线程调用notify、notifyAll方法来将其唤醒
②其他线程调用interrupt来将其唤醒
③wait方法本身超时
当执行了下面的代码:
obj.wait();
我们可以说当前线程在obj上发生了等待,当前线程进入了obj的“等待队列”,此时当前线程会让出锁,让其他线程继续竞争获得该实例的锁(因此这里有个规则,调用wait的线程必须持有当前实例对象的锁)
过程如下图:

图3
3.2:notify
现在先来介绍下notify,该方法会将等待队列里的线程取出,让其退出等待并参与锁竞争然后继续执行上次wait后没有执行完的语句。整体过程如下图所示:

图4
可以看到,t1在被挂起后,会因为t2调用了同实例的notify方法,而让t1被从等待队列里释放,重新加入到所得竞争力,t2执行完毕后释放锁,锁又再次被t1竞争到,t1将继续执行上次被挂起时后面未执行完的语句。
需要指出的是,如果等待队列里的线程是多个,那么被唤醒的那一个,将会是等待队列里所有线程随机的一个,不会特定哪一个线程会被唤起。
3.3:notifyAll
接下来介绍notifyAll方法,顾名思义,就是将等待队列里的线程全部唤起,然后这些线程将全部加入到锁竞争,竞争到,继续完成上次被挂起时未执行完毕的操作,流程图如下:

图5
说明,当线程调用实例的wait、notify、notifyAll方法有个大前提,就是必须要求该线程拥有该实例的锁,否则会抛IllegalMonitorStateException异常。
在编写程序时,是该选择notify还是选择notifyAll?这个可以指出的是,notifyAll往往更加健壮,而notify由于唤起的线程少,因此效率会更高,但是存在程序停止的风险。
附上使用wait、notify进行线程通信的例子:
[温故]图解java多线程设计模式(一)的更多相关文章
- [温故]图解java多线程设计模式(二)
join & interrupt 这俩方法属于线程对象里的方法,属于线程本身的操作. join方法 用于等待一个线程的终止,等待期间将会阻塞,直到被等待的线程终止结束. 所以join可以用来做 ...
- 《图解Java多线程设计模式》读书笔记
略读中...后面详读的时候,补充经典图片和文字说明
- 图解java多线程设计模式之一一synchronized实例方法体
synchronized实例方法体和synchronized代码块 synchronied void method(){ ....... } 这个等同于下面将方法体用synchronized(this ...
- java多线程设计模式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt220 java多线程设计模式 java语言已经内置了多线程支持,所有实现Ru ...
- Java多线程设计模式(一)
目录(?)[-] Java多线程基础 Thread类的run方法和start方法 线程的启动 线程的暂时停在 线程的共享互斥 线程的协调 Single Threaded Execution Patte ...
- Java多线程设计模式(4)线程池模式
前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将“委托消息的一端”和“执行消息的一端”用两个不同的线程来实现.该线程模式 ...
- Java多线程设计模式(四)
目录(?)[-] Future Pattern Two-Phase Termination Pattern Thread-Specific Storage Pattern Active Object ...
- Java多线程设计模式(三)
目录(?)[-] Read-Wirte Lock Pattern Thread-Per-Message Pattern Worker Thread Pattern Read-Wirte Lock ...
- Java多线程设计模式(二)
目录(?)[-] Guarded Suspension Pattern Balking Pattern Producer-Consumer Pattern Guarded Suspensi ...
随机推荐
- nignx重启
.进入nginx安装目录sbin下 .输入./nginx -s reload
- [Training Video - 1] [Introduction to Web services]
What is a web service? http://webservicex.net/ws/default.aspx WebService是一种跨编程语言和跨操作系统平台的远程调用技术. 跨编程 ...
- ubuntu系统下安装pyspider:解决pyspider启动时不启动phantomjs问题
问题描述: 在建立第一个虚拟环境时,运行pyspider正常.建立第二个虚拟环境时,运行pyspider再现下面错误.应该是phantomjs没有启动成功. 错误代码:(phantomjs:21507 ...
- ASP.Net Web API 输出缓存(转)
出处:http://www.cnblogs.com/ajilisiwei/p/6112078.html 原文的转载地址:http://www.strathweb.com/2012/05/output- ...
- ADF文件在哪个地方?
Where is ADF file on Tango Device? Ask Question up vote2down votefavorite I have a Tango tablet de ...
- css 颜色渐变 兼容性
参考文献:http://caibaojian.com/css3-background-gradient.html https://www.cnblogs.com/xzzzys/p/7495725 ...
- WebApi 插件式构建方案:重写的控制器获取工厂
body { border: 1px solid #ddd; outline: 1300px solid #fff; margin: 16px auto; } body .markdown-body ...
- solr-4.10.2版本使用tomcat7部署
当前版本仅限于solr-4.10.2版本.默认环境使用的是jdk1.7,tomcat7.环境自己配置.网上一堆堆的. 1.下载相应的文件(solr-4.10.2.zip). 官网地址:http://l ...
- eclipse-->run as --> maven test 中文乱码
其有一个配置参数forkMode,默认为once,即表示每次运行test时,新建一个JVM进程运行所有test. 这可能会导致乱码问题.首先将forkMode设置为never,即不新建.再运行mvn ...
- asp.net 添加错误日志
在开发程序中,错误日志很有必要.今天就把使用到的添加错误日志,记录下来,方便以后查看 利用的asp.net错误处理机制 Application_Error 贴出代码 protected void Ap ...