关于java多线程浅析三:每个对象都有的方法
2017-05-11 23:44
197 查看
先明确一下一些基本的概念。
1 串行、并行与并发的区别:
不搞那些晦涩的定义,讲一个简单的例子,可能不恰当,但基本上是这个意思。
就拿一个很简单的例子来说吧,下班回家后,你想做饭,但你又想打晋级赛,你想了想,算了,还是打完了晋级赛再做饭吧,好吧,这就是串行,做完一件事再做另外一件事;还有一种方法是,你选择玩亚索发大招的瞬间抽个空去厨房把菜洗了,当然你会死的很惨,这样打一会LOL再洗个菜,然后回来继续放你的QWER,这就是并发。还有就是你让你女朋友去做饭,你去打LOL,(当然这样你也会死得很惨),这就是并行。
2 线程安全与同步
线程安全就是指在多线程运行程序的情况下,每一次的运行结果都是和单线程实现相同逻辑代码的运行结果一致,或者说是能确保每一次运行得到的结果都是期望正确的值,那就是线程安全的。
那什么是同步呢?同步就是指通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。说白了,就是要对多线程进行有效的管理,以保证每个线程都能正确的访问共享资源。
那么问题就出来了,怎么才能对多线程进行有效的控制和调度呢?既然要到线程进行控制,那么首先就需要有这么一个监控器来进行监控。
监控器Monitor是java中用以实现线程之间的互斥与协作的一种机制,可以把Monitor简单理解成对象或者class的锁。每一个对象都有成为Monitor的潜质,当然,每一个对象有且仅有一个Monitor。它的作用就是来监测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在synchronized 范围内,监视器发挥作用。每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”(等待锁的获取),而在 “Wait Set”中等待的线程状态是 “in Object.wait()”(等待线程被唤醒)。
举了简单的例子说明:
上面的代码很简单,就是在main函数里启动一个继承了Thread类的线程t1,然后调用wait()方法。在t1的run()方法里调用notify()方法。但值得注意的是,我们在main函数以及ThreadA类里的run方法上,都用到了synchronized关键字,一个传递的是对象t1,一个是this关键字,但在这段代码里,可以确定它们都是这个t1对象。回顾一下上面说过的每个对象都有且仅有一个monitor,再看一下运行的结果,再进行进一步分析:
明明是代码里是t1.wait(),为什么等待的确实main线程呢?这是因为wait函数的语义是使当前线程等待,也就是途中所描述的“Active Thread”。当main函数执行 synchronized (t1) 代码段时,main线程获得了对象t1 的 monitor,当t1.start( )时,t1线程也执行相同语义的代码synchronized (this) 时,因为monitor已经被main线程所获得,t1只能进入Wait Set”里面等候。当调用t1.wait()时,就会将正在monitor中的处于“Active Thread”状态的main线程置于“Wait Set”里面等待,也就是浅析二中线程状态图中的“等待Blocked”状态,此时正在Wait Set”里面等待的t1线程就马上获得了CPU的执行权,变成了Active Thread”。再调用notify()方法后,main线程进入“锁定Blocked”状态,随时等待t1线程继续执行完毕后得到t1释放的monitor,进入就绪状态,然后main函数执行完毕。
1 串行、并行与并发的区别:
不搞那些晦涩的定义,讲一个简单的例子,可能不恰当,但基本上是这个意思。
就拿一个很简单的例子来说吧,下班回家后,你想做饭,但你又想打晋级赛,你想了想,算了,还是打完了晋级赛再做饭吧,好吧,这就是串行,做完一件事再做另外一件事;还有一种方法是,你选择玩亚索发大招的瞬间抽个空去厨房把菜洗了,当然你会死的很惨,这样打一会LOL再洗个菜,然后回来继续放你的QWER,这就是并发。还有就是你让你女朋友去做饭,你去打LOL,(当然这样你也会死得很惨),这就是并行。
2 线程安全与同步
线程安全就是指在多线程运行程序的情况下,每一次的运行结果都是和单线程实现相同逻辑代码的运行结果一致,或者说是能确保每一次运行得到的结果都是期望正确的值,那就是线程安全的。
那什么是同步呢?同步就是指通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。说白了,就是要对多线程进行有效的管理,以保证每个线程都能正确的访问共享资源。
那么问题就出来了,怎么才能对多线程进行有效的控制和调度呢?既然要到线程进行控制,那么首先就需要有这么一个监控器来进行监控。
监控器Monitor是java中用以实现线程之间的互斥与协作的一种机制,可以把Monitor简单理解成对象或者class的锁。每一个对象都有成为Monitor的潜质,当然,每一个对象有且仅有一个Monitor。它的作用就是来监测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在synchronized 范围内,监视器发挥作用。每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”(等待锁的获取),而在 “Wait Set”中等待的线程状态是 “in Object.wait()”(等待线程被唤醒)。
举了简单的例子说明:
public class MyThread { public static void main(String[] args) { try { ThreadA t1 = new ThreadA("t1"); synchronized (t1) { System.out.println(Thread.currentThread().getName()+"线程启动线程 t1"); t1.start(); System.out.println(Thread.currentThread().getName()+"线程等待被唤醒"); t1.wait(); System.out.println(Thread.currentThread().getName()+"线程继续执行"); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class ThreadA extends Thread{ public ThreadA(String name){ super(name); } public void run(){ synchronized (this) { System.out.println(Thread.currentThread().getName()+"线程执行 notify 方法"); notify(); } } }
上面的代码很简单,就是在main函数里启动一个继承了Thread类的线程t1,然后调用wait()方法。在t1的run()方法里调用notify()方法。但值得注意的是,我们在main函数以及ThreadA类里的run方法上,都用到了synchronized关键字,一个传递的是对象t1,一个是this关键字,但在这段代码里,可以确定它们都是这个t1对象。回顾一下上面说过的每个对象都有且仅有一个monitor,再看一下运行的结果,再进行进一步分析:
main线程启动线程 t1 main线程等待被唤醒 t1线程执行 notify 方法 main线程继续执行
明明是代码里是t1.wait(),为什么等待的确实main线程呢?这是因为wait函数的语义是使当前线程等待,也就是途中所描述的“Active Thread”。当main函数执行 synchronized (t1) 代码段时,main线程获得了对象t1 的 monitor,当t1.start( )时,t1线程也执行相同语义的代码synchronized (this) 时,因为monitor已经被main线程所获得,t1只能进入Wait Set”里面等候。当调用t1.wait()时,就会将正在monitor中的处于“Active Thread”状态的main线程置于“Wait Set”里面等待,也就是浅析二中线程状态图中的“等待Blocked”状态,此时正在Wait Set”里面等待的t1线程就马上获得了CPU的执行权,变成了Active Thread”。再调用notify()方法后,main线程进入“锁定Blocked”状态,随时等待t1线程继续执行完毕后得到t1释放的monitor,进入就绪状态,然后main函数执行完毕。
相关文章推荐
- Thin的DateChooser代码学习(关于js的函数参数为一个完整的函数以及“对象不支持此属性或方法”错误的解决)(原创,转载请声明)
- 面向对象的编程:关于对象的 属性、方法和事件 的理解
- 关于automation服务器不能创建对象解决方法
- 为什么Java的每个对象都有wait()/notify()方法?
- 关于RecordSet对象指针移动方法
- 关于oracle中大对象处理的一些方法和实例
- 关于数据库对象所有者非dbo时的可能造成的问题及解决方法
- 关于【对象“***.rem”已经断开连接或不在服务器上】异常的解决方法
- 关于IE7打开任何网页弹出[未处理的异常('对象不支持此属性或方法')发生在iexplorer.exe]错误调试框的解决办法
- 05_传智播客hibernate教程_实体对象的三种状态与saveOrUpdate方法 2 关于delete后的状态
- 关于submit() 对象不支持此属性或方法的解决方法
- 1-(E-teller)关于向T4Table组件返回多个对象的方法
- 关于多态性的动态绑定问题, 对象调用方法的执行过程.
- 关于submit() 对象不支持此属性或方法的解决方法
- 关于在java中List取值的方法(List中是数据对象)!
- 关于面向对象继承实方法和虚方法
- 关于对象数据库 DB4O 的一些BUG以及如何应对的方法
- session对象关于removeValue方法的验证
- 关于oracle中大对象处理的一些方法和实例
- 关于【对象“***.rem”已经断开连接或不在服务器上】异常的解决方法