以下是我的实现代码,希望大伙儿给点意见,如果有朋友也写了相同实现功能的代码,希望可以贴出来让我学习一下:主类package doublethreads;public class PrintNum {
public static void main(String[] args) {
EvenThread et = new EvenThread();
OddThread ot = new OddThread();
et.setOddThread(ot);
ot.setEvenThread(et);
et.start();
ot.start();
while (true) {
// 一直循环检测直至两个线程都准备好要输出了。
if (et.ready() && ot.ready()) {
// 都准备好了之后点燃导火线,启动输出。
et.toPrint(0);
break;
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出偶数的线程:package doublethreads;public class EvenThread extends Thread {
/** 本次的输出数字。 */
private int num;
private boolean enablePrint;
private boolean run;
private boolean wait;
private OddThread ot; public EvenThread() {
num = 0;
enablePrint = false;
run = true;
wait = false;
} public void setOddThread(OddThread ot) {
this.ot = ot;
} public synchronized void toPrint(int num) {
this.num = num;
// 继续输出
notify();
} public synchronized void run() {
while (run) {
if (enablePrint == false) {
try {
// System.out.println("Even Wait...");
wait = true;
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even: " + num);
// 下一次输出奇数,暂停输出
enablePrint = false;
ot.toPrint(num + 1);
// 偶数输出到10终止。
if (num == 10) {
run = false;
System.out.println("Even exit");
break;
}
}
} /** 获取是否可以开始输出。为true的条件为本线程进入到wait()状态并且ot不为空。 */
public boolean ready() {
if (wait == false) {
return false;
}
if (ot == null) {
return false;
}
return true;
}
}
输出奇数的线程:package doublethreads;public class OddThread extends Thread {
/** 本次的输出数字。 */
private int num;
private boolean enablePrint;
private boolean run;
private EvenThread et;
private boolean wait; public OddThread() {
num = 0;
enablePrint = false;
run = true;
wait = false;
} public void setEvenThread(EvenThread et) {
this.et = et;
} public synchronized void toPrint(int num) {
this.num = num;
//继续输出
notify();
} public synchronized void run() {
while (run) {
if (enablePrint == false) {
try {
// System.out.println("Odd Wait...");
wait = true;
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Odd: " + num);
// 下一次输出偶数,暂停输出
enablePrint = false;
et.toPrint(num + 1);
// 奇数输出到9终止。
if (num == 9) {
run = false;
System.out.println("Odd exit");
break;
}
}
} /** 获取是否可以开始输出。为true的条件为本线程进入到wait()状态并且et不为空。 */
public boolean ready() {
if (wait == false) {
return false;
}
if (et == null) {
return false;
}
return true;
}
}

解决方案 »

  1.   

    按照你的思路,刚刚我也写了一个,切磋一下。package com.google.algorithm;import java.util.concurrent.Semaphore;
    import java.util.concurrent.atomic.AtomicInteger;public class PrintNum
    {
    private static AtomicInteger s_number = new AtomicInteger();

    public static void main(String[] args){
    Semaphore semp1 = new Semaphore(0);
    Semaphore semp2 = new Semaphore(1);

    OddThread ot = new OddThread(semp1, semp2);
    EvenThread et = new EvenThread(semp2, semp1);

    ot.start();
    et.start();

    }

    static class OddThread extends Thread{

    private Semaphore write;
    private Semaphore wait; 

    public OddThread(Semaphore write, Semaphore wait)
    {
    super();
    this.write = write;
    this.wait = wait;
    } public void run(){
    while(s_number.get() < 100){
    try
    {
    write.acquire();
    System.out.println("Output Odd: " + s_number.getAndIncrement());

    catch (InterruptedException e)
    {
    e.printStackTrace();
    }finally{
    wait.release();
    }
    }
    }
    } static class EvenThread extends Thread{

    private Semaphore write;
    private Semaphore wait; 

    public EvenThread(Semaphore write, Semaphore wait)
    {
    super();
    this.write = write;
    this.wait = wait;
    }

    public void run(){
    while(s_number.get() < 100){
    try
    {
    write.acquire();
    System.out.println("Output Even: " + s_number.getAndIncrement());

    catch (InterruptedException e)
    {
    e.printStackTrace();
    }finally{
    wait.release();
    }
    }
    }
    }
    }
      

  2.   

    回一楼,我只是想练习练习双线程。请教二楼,import java.util.concurrent.Semaphore;
    import java.util.concurrent.atomic.AtomicInteger;这两个类我都是第一次见,能解释一下是什么用法吗?谢谢...
      

  3.   


    import java.util.concurrent.Semaphore;
    //信号量Semaphore,学过操作系统么没 型号量是解决同步和互斥文提的一个经典
    import java.util.concurrent.atomic.AtomicInteger;
    //atomic是Java提供的单变量对线程并发的安全访问包,AtomicInteger一个能被多线程安全操作
    //的int整数值
      

  4.   


    给你们发个例子其实说到线程,学好了操作系统这门课,编程就觉对不难了 
    个人觉得操作系统很多的思想在编程中太重要了

    class R1 implements Runnable{ @Override
    public void run() {
    synchronized(System.out){//在这两个线程中可以说标准输出流是临界资源,
                 //一个访问了,另一个就不能访问
    for(int i=0; i<100; i+=2){
    // 输出偶数
    System.out.println("Even:" + i);
    System.out.notifyAll();
    try {
    System.out.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    System.out.notifyAll();//活动的线程结束了,确保其他的线程被唤醒
    }
    }
    }class R2 implements Runnable{ @Override
    public void run() {
    synchronized(System.out){//在这两个线程中可以说标准输出流是临界资源,
                         //一个访问了,另一个就不能访问
    for(int i=1; i<100; i+=2){
    // 输出奇数
    System.out.println("Odd :" + i);
    System.out.notifyAll();
    try {
    System.out.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    System.out.notifyAll();//活动的线程结束了,确保其他的线程被唤醒
    }
    }
    }class PrintNum{
    public static void Print(){
    new Thread(new R1()).start();
    new Thread(new R2()).start();
    }
    }
      

  5.   


    呵呵,我觉得这个想法很好。看了后我直笑...不过,我想的是只对两个thread进行协调,不使用除thread之外的其它类。单纯Thread。
      

  6.   

    有个问题是如何保证先输出0,再输出1,再输出2...
    我使用了一个while(){}循环来确保输出的顺序,这也是我感觉最大的别扭所在。
    这个版本的输出可能会输出:
    Odd :1
    Even:0
    Odd :3
    Even:2
    Odd :5
    Even:4
    Odd :7
    Even:6
    Odd :9
    Even:8
      

  7.   


    哦 你是觉得我写的什么是Thread之外的类
    也许是我理解错了 你是想自己写两个线程 让这两个线程来同步 可同步的标识过程是自己来写
    自己来试试
    不过逻辑上似乎有点问题
    看你代码
       public synchronized void run() {
            while (run) {
                if (enablePrint == false) { // 我想知道这个enablePrint什么时候为true
                    try {                   // 看了半天没有这句话过enablePrint=true;
                        // System.out.println("Even Wait...");
                        wait = true;
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Even: " + num);
                // 下一次输出奇数,暂停输出
                enablePrint = false;
                ot.toPrint(num + 1);
                // 偶数输出到10终止。
                if (num == 10) {
                    run = false;
                    System.out.println("Even exit");
                    break;
                }
            }
        }
      

  8.   


    嗯,我承认这是我画蛇添足的地方,谢谢了。
    修改后,直接删除了enablePrint这个成员变量,如下:
    public synchronized void run() {
    while (run) {
    try {
    // System.out.println("Even Wait...");
    wait = true;
    wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("Even: " + num);
    ot.toPrint(num + 1);
    // 输出到10终止。
    if (num == 10) {
    run = false;
    System.out.println("Even exit");
    break;
    }
    }
    }
      

  9.   


    昨晚睡了 没看到问题 今天没课有时间来解决
    想了一下,这个可以因 类似生产者----消费者的设计模式来解决 
    写了个 看看行不 
    class EvenThread extends Thread{

    PrintNumResource pnr;

    public EvenThread(PrintNumResource pnr) {
    super();
    this.pnr = pnr;//得到资源
    }
    @Override
    public void run() {
    while(!pnr.isTooBig()){// 没有过大就输出
    pnr.PrintEven();
    }
    }
    }class OddThread extends Thread{ PrintNumResource pnr;

    public OddThread(PrintNumResource pnr) {
    super();
    this.pnr = pnr; //得到资源
    } @Override
    public void run() {
    while(!pnr.isTooBig()){ // 没有过大就输出
    pnr.PrintOdd();
    }
    }
    }class PrintNumResource{

    int iNum = 0;
    public final static int MAX = 10;
    private synchronized void addNum(){
    iNum++;
    }
    public synchronized boolean isTooBig(){
    return iNum > MAX;
    }
    public synchronized void PrintEven(){
    try{
    if(iNum % 2 == 0){ //是偶数 可以输出
    System.out.println("Even: " + iNum);
    this.addNum(); //输出后加1;
    this.notifyAll(); //唤醒其他的等待进程
    }else{
    System.out.println("Now is not Even ,wait");
    this.wait(); //不符合要等待
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    }

    public synchronized void PrintOdd(){
    try{
    if(iNum % 2 == 1){ //是奇数 可以输出
    System.out.println("Odd: " + iNum);
    this.addNum(); //输出后加1;
    this.notifyAll(); //唤醒其他的等待进程
    }else{
    System.out.println("Now is not Odd ,wait");
    this.wait(); //不符合要等待
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    } public static void Print(){ //测试函数 两种不同的顺序
    PrintNumResource pnr1 = new PrintNumResource();
    new OddThread(pnr1).start();
    new EvenThread(pnr1).start();

    PrintNumResource pnr2 = new PrintNumResource();
    new EvenThread(pnr2).start();
    new OddThread(pnr2).start();
    }
    }
      

  10.   

    学习了,真想看看更多的版本,希望有纯粹是两个Thread之间进行协调,效率高点的代码。等待ing...
      

  11.   

    两个线程做的事情都是一样的,所以不需要写两个class。
    题目的要求是两个线程轮流输出,不存在并发的情况。用concurrent类不是好的选择。public class MTNS extends Thread
    {
        MTNS peer;
        int value;
        int maxValue;
        boolean isOwner;
        MTNS(String name,int init,int maxValue)
        {
            super(name);
            this.value = init;
            this.maxValue = maxValue;
            this.isOwner = init == 0;
        }
        synchronized void waitForPeer() throws InterruptedException
        {
            while(!isOwner)
                this.wait();
            isOwner = false;
        }
        synchronized void notifyThis()
        {
            isOwner = true;
            this.notify();
        }
        public void run()
        {
            try
            {
                while(value <= maxValue)
                {
                    waitForPeer();
                    System.out.println(getName() + ":" + this.value);
                    this.value += 2;
                    peer.notifyThis();
                }
            }
            catch(Exception ex)
            {
                ex.printStackTrace();
            }
        }
        public static void main(String[] args)
        {
            try
            {
                MTNS even = new MTNS("even",0,10);
                MTNS odd = new MTNS("odd",1,10);
                even.peer = odd;
                odd.peer = even;
                even.start();
                odd.start();
            }
            catch(Exception ex)
            {
                ex.printStackTrace();
            }
        }}
      

  12.   


    我想请教一下taolei,MTNS实例even中执行this.notify()时,只是notify() even这个实例的线程吧,不会notify()到odd的线程吧?(假设如果even和odd都处于wait()的话,假设一下)
      

  13.   

    public void run() {
            synchronized(System.out){//在这两个线程中可以说标准输出流是临界资源,
                                    //一个访问了,另一个就不能访问            
                for(int i=0; i<100; i+=2){
                // 输出偶数
                    System.out.println("Even:" + i);
                    System.out.notifyAll();//这里表示当前一个线程完成了,然后唤醒其他的线程
                    try {
                        System.out.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.notifyAll();//活动的线程结束了,确保其他的线程被唤醒
            }        //上面已经唤醒其他线程了,这里为什么还要再加一句    }为什么
      

  14.   

    两个线程是轮流获得输出控制的,不会同时wait.
    基本原理就是有输出控制权的线程输出结果后把控制权交给另一个线程,然后等待另一个线程交回控制权。
      

  15.   

    才学线程,有的地方看不懂!我提一个建议!如果想2个线程的顺序输出,为什么不使用一个公有boolean 变量!  当为true时输出偶数!为false时输出奇数!
      

  16.   


    哦。
    其实困扰我的是:
    如果thread1处于wait,thread2也处于wait(),执行thread1.notify()时,根据API的说明,是从处于wait()队列的线程中随机的notify()一个,是不是有可能notify thread1也有可以notify thread2啊??还是说thread1.notify()只能notify本身呢??