建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。

转载 2016年08月31日 10:41:37
/**
 * 建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。
 * 这个问题用Object的wait(),notify()就可以很方便的解决。
 * 
 * 主要的思想就是,为了控制执行的顺序,必须要先持有prev锁,也就前一个线程要释放自身对象锁,再去申请自身对象锁,
 * 两者兼备时打印,之后首先调用self.notify()释放自身对象锁,唤醒下一个等待线程,再调用prev.wait()释放prev对象锁,
 * 终止当前线程,等待循环结束后再次被唤醒。
 * 
 * 程序运行的主要过程就是A线程最先运行,持有C,A对象锁,后释放A,C锁,唤醒B。线程B等待A锁,再申请B锁,后打印B,
 * 再释放B,A锁,唤醒C,线程C等待B锁,再申请C锁,后打印C,再释放C,B锁,唤醒A。
 * 
 * wait导致当前的线程等待,直到其他线程调用此对象的 notify() 要领或 notifyAll() 要领。当前的线程必须拥有此对象监视器。该线程揭晓对此监视器的一切权并等待,直到其他线程议决调用 notify 要领,或 notifyAll 要领告诉在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得 对监视器的一切权后才能继续执行.

   notify唤醒在此对象监视器上等待的单个线程。假如一切线程都在此对象上等待,则会挑选唤醒其中一个线程。直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。此要领只应由作为此对象监视器的一切者的线程来调用.

  "当前的线程必须拥有此对象监视器"与"此要领只应由作为此对象监视器的一切者的线程来调用"表明 wait要领与notify要领必须在同步块内执行,即synchronized(obj之内).

  调用对像wait要领后,当火线程释放对像锁,进入等待形状 .直到其他线程(也只好是其他线程)议决 notify 要领,或 notifyAll.该线程重新获得 对像锁.

  继续执行,记得线程必须重新获得 对像锁才能继续执行.由于 synchronized代码块内没有锁是寸步无法走的.

	notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:

	notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
	notify则文明得多他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。
 */
package t;


public class MyThreadPrinter2 implements Runnable {   
  
    private String name;   
    private Object prev;   
    private Object self;   
  
    private MyThreadPrinter2(String name, Object prev, Object self) {   
        this.name = name;   
        this.prev = prev;   
        this.self = self;   
    }   
  
    @Override  
    public void run() {   
        int count = 10;   
        while (count > 0) {   
        	//同步块,加锁
            synchronized (prev) {   
                synchronized (self) {   
                    System.out.print(name);   
                    count--;  
                   /* try{
                    Thread.sleep(1);
                    }
                    catch (InterruptedException e){
                     e.printStackTrace();
                    }*/
                    
                    self.notify(); //唤醒在此对象监视器上等待的单个线程(即等待给self加锁的线程)。假如多个线程都在此对象上等待,则会挑选唤醒其中一个线程。
                }//self解锁,被唤醒的线程此时可以给self加锁了。   
                try {   
                    prev.wait();   //该线程暂时释放prev的锁,等待再次获得prev的锁,然后执行下面的语句。此时prev还需要被唤醒
                } catch (InterruptedException e) {   
                    e.printStackTrace();   
                }   
            }   
  
        }   
    }   
  
    public static void main(String[] args) throws Exception {   
        Object a = new Object();   
        Object b = new Object();   
        Object c = new Object();   
        MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a);   
        MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b);   
        MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c);   
           
           
        new Thread(pa).start();//c a加锁,a输出'A',a唤醒pb,a解锁(synchronized (a){}同步块结束),c.wait()->该线程pa等待(c暂时解锁,直至其它线程执行c.notify()之后,该线程pa才能继续执行(即被唤醒)---可以理解为等待c的通知)
        Thread.sleep(10);//在单线程下,Thread.sleep(10000)让你的线程“睡眠”10000ms,也就是不工作,因为是单线程,所以要等到过了10000ms之后,该子线程继续工作。
        //多线程下,睡眠的线程main先不工作,让其余的子线程先工作,等过了10000ms之后,它再重新回到线程的等待队伍中,开始工作。
        //main睡眠10ms结束后,执行下面的语句,即new Thread(pb).start();----pb线程启动后,main再睡眠10ms,接着启动pc。这样不让pb和pc相邻启动,避免pc和pb竞争(因为开始时pc和pb都符合条件)
        new Thread(pb).start();//a b加锁,b输出'B',b唤醒pc,b解锁,a.wait()->该线程pb等待(c暂时解锁,直至其它线程执行a.notify()之后,该线程pb才能继续执行)
        Thread.sleep(10);
        new Thread(pc).start();//b c加锁,c输出'C',c唤醒pa,c解锁,b.wait()->该线程pc等待(b暂时解锁,直至其它线程执行b.notify()之后,该线程pc才能继续执行)
        Thread.sleep(10);
    }   
}  

 
转载地址:http://blog.csdn.net/code_jober/article/details/10001413

相关文章推荐

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。

/** * 建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。 * 这个问题用Object的wait(),notify()就可以很方...

多线程(至少三个线程)分别打印A、B、C,要求按ABC的顺序循环打印10次。

看到网上一道题,三个线程按顺序打印A、B、C循环10次,于是自己按几种方法也写了一下: 一、用线程池、Lock锁和condition(Object 监视器方法的使用)组合使用实现: package...

启动三个线程A,B,C,打印10次 按照ABC的顺序输出

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util...

有三个线程名字分别是A、B、C,每个线程只能打印自己的名字,在屏幕上顺序打印 ABC,打印10次。

今天去面试的时候,遇到的笔试题,当时没有想到,回来学习记录下。今天去面试的时候,遇到的笔试题,当时没有想到,回来学习记录下。 public class TestPrintOrder { publi...

有三个线程ID分别是A、B、C,请有多线编程 实现 在屏幕上循环打印10次ABCABC......

有三个线程ID分别是A、B、C,请有多线编程 实现 在屏幕上循环打印10次ABCABC...... 代码如下: package thread1; public class Main_thread1...

有三个线程名字分别是A、B、C,每个线程只能打印自己的名字,在屏幕上顺序打印 ABC,打印10次。不准使用线程的sleep()

public class ABC1 extends Thread { private static Object o = new Object(); private static int coun...

开启3个线程依次打印ABC10次

题目: 编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。 #includ...

一道Java线程面试题。3个线程顺序打印10次ABC.

一道Java线程面试题。3个线程顺序打印10次ABC. 2011-06-12 00:30 原文出处http://hi.baidu.com/dapplehou/blog/item/1...
  • zqfddqr
  • zqfddqr
  • 2011年08月07日 20:27
  • 881

用三个线程控制循环输出10次ABC

public class PrintABC_Syn { private static final int MAXN = 30; private int count = 0; ...

主线程和子线程均循环10次,两者交替运行50次

我们应该时时保持面向对象编程的思想,可以将主子线程封装到一个类中(类中的方法是两个有关联的方法) ,使用标记变量可以人为的控制线程的执行。 import java.util.ArrayList; ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。
举报原因:
原因补充:

(最多只允许输入30个字)