Java多线程中的wait和notifyAll

来源:互联网 发布:linux如何关闭echo 编辑:程序博客网 时间:2024/06/05 13:33

        想要直接看代码的可以跳过下面我对并发的简单理解,直接看代码(我已经加了注释,代码写的有问题还请诸位大神指出,以免误人子弟)。

        最近要用到Java多线程,才好好的看了一下多线程。谁知道这货写起来这么麻烦,还要考虑各种锁,还要考虑各种共享,各种交互。我就奇怪了,Java设计者怎么就不给程序员提供方便的同步机制,每次都要锁锁锁的,万一控制不好还死锁,妹的,简直不能忍。不过话说回来,Java的属性和方法可以是private、protected、public的,方法可以不用synchronized等等天性让它的并行安全性大大降低,并行处理也变得难上加难。

        这里的wait、notifyAll、notify是Object类的方法,分别对应条件对象Condition中的await、signalAll、signal方法。它们的字面意思是一样的,作用也差不多。

        这时你就要问了:我就想知道wait和notifyAll,你给我说Condition干嘛!其实是这样的:在synchronized出世前,Java程序员普遍采用显式加锁、显式附加锁的条件对象来解决并发问题。而Java1.0以后每个对象都有一个内部锁而且该锁有一个内部条件,所以可以用synchronized关键字来控制某个对象或方法的并发访问,这样也避免了过多显式地加锁和释放锁。所以synchronized是 Lock和Condition的一种特殊简写。

        condition.awit()<-->object.wait():当前线程被阻塞并放弃锁,进入该条件的等待集。直到另一个线程调用同一条件对象的signalAll()为止。(因此,当锁可用时并不一定能马上解除阻塞,还得等条件满足才行。这也是和那些单纯地等待锁的线程的区别)。

        condition.signalAll()<-->object.notifyAll():将所有线程从它的等待集中移出,使之成为可运行的,此时线程应再次测试一下该条件(通常利用while循环)。这里要注意一点signal()方法只会随机地移出某个等待线程而不是全部,所以如果某个线程没被signal通知到就会一直被阻塞容易出现死锁。

       object.wait()和object.notifyAll()方法跟上面说的condition类似,不过想要使用object.wait()和object.notifyAll()必须先获得object的对象锁(也就是放在synchronized代码块中)。好吧如果你不相信我,可以看一下其它大牛们写的关于object.wait()和object.notifyAll()的分析,看和condition.awit()是不是类似。

        好了,说了这么多,下面来看一下下面的代码:我就是单纯地想开一个子线程来完成一个循环处理的工作,我在主线程中能灵活控制这个子线程的开始、暂停/继续、结束。简单吧?对我一个24k纯菜鸟来说可真的不简单,下面是我的实现:

public class MainActivity {private String isCycleFlag[] = { "true" };// 是否要求循环,默认可以循环private String isDeadFlag[] = { "false" };// 是否要求线程退出,默认不退出class CycleThread extends Thread {public CycleThread(String name) {// 通过构造器给线程命名super(name);}public void run() {run_label: while (!Thread.currentThread().isInterrupted()) {// 这里可耻的利用了Java标签breaksynchronized (isDeadFlag) {// 获得isDeadFlag对象锁while (isDeadFlag[0].equals("true")) {// 如果要求线程死亡,直接break无限循环break run_label;// 跳出while就到了run方法的末尾,run方法执行完了,线程的使命也就完成了// return;}}synchronized (isCycleFlag) {// 获得isCycleFlag对象锁while (isCycleFlag[0].equals("false")) {// 如果要求循环终止,直接阻塞当前线程并释放对象锁try {System.out.println(getName() + " waiting 4 second!");isCycleFlag.wait();// 进入等待集,等着被“叫醒”} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(getName() + " start Cycle!");// 真正开始干活}try {Thread.sleep(1000);// 让它睡一秒再自动醒过来,为了更好地看到输出} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// whileSystem.out.println(getName() + " end!");// 线程干完活了}// run}// Thread classpublic void onResume() {synchronized (isCycleFlag) {// 获得isCycleFlag对象锁isCycleFlag[0] = "true";// 给isCycleFlag对象赋值isCycleFlag.notifyAll();// “叫醒”所有因为 要求循环终止 而阻塞的线程,继续循环}}public void onStop() {synchronized (isCycleFlag) {isCycleFlag[0] = "false";isCycleFlag.notifyAll();// 要求循环终止}}public void onDestory() {synchronized (isCycleFlag) {// 子线程此时可能被阻塞,这里先“叫醒”线程再终止它。(好吧,我承认我没想到怎么终止被阻塞的线程,只能先叫醒它)isCycleFlag[0] = "true";isCycleFlag.notifyAll();}synchronized (isDeadFlag) {isDeadFlag[0] = "true";isDeadFlag.notifyAll();}}public static void main(String[] args) throws InterruptedException {MainActivity test = new MainActivity();CycleThread cycleThread = test.new CycleThread("CycleThread");cycleThread.start();// 启动子线程(循环线程)try {Thread.sleep(4000);// 让主线程睡四秒,让子线程先运行着} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}test.onStop();// 要求循环终止try {Thread.sleep(4000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}test.onResume();// 要求继续循环try {Thread.sleep(4000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}test.onDestory();// 要求子线程停止}}
就一个Java工程,里面一个MainActivity.java文件。所有的代码都在这了,大家可以运行试一下,有什么建议(或者要批评的)尽管说,我好学习一下。

0 0
原创粉丝点击