线程的执行时序是不能决定的。因为线程时序会根据jdk版本、操作系统的不同,有很大的不同。因此即使你得到了想要的结果,换一个jdk或者操作系统或者在多cpu平台上执行,结果很可能会完全不一样。因此写多线程程序,最好不要依赖线程时序。这样是不能跨平台的。不但依赖于程序运行时的操作系统,甚至会依赖于当前的软硬件配置。如果你想得到固定顺序(线性顺序)的输出又为什么要用都线程呢?

解决方案 »

  1.   

    只有同一个对象的synchronized的函数才共用一个机锁
    class Thread1 extends Thread{
      private synchronized void countCreate()class Thread2 extends Thread
      private synchronized void countCreate()
    你这两个类中两个countCreate函数分别是对应了两个对象的机锁(一个是Thread1对象,一个是Thread2对象拥有的 ),根本就没法实现你的需求改正:把synchronized countCreate函数作为类FinalCount的成员函数,Thread1和Thread2
    的run中再调用countCreate
      

  2.   

    我按照各位大侠的意见做了修改如下
    package testthread;
    /**
     * <p>Title: </p>
     * <p>Description: </p>
     * <p>Copyright: Copyright (c) 2003</p>
     * <p>Company: </p>
     * @author unascribed
     * @version 1.0
     */
    class FinalCount{
      public static int y=1;
      public static synchronized void countCreate1(){
        for(int i=0;i<5;i++){
          System.out.println(FinalCount.y);
          ++FinalCount.y;
        }
      }
      public static synchronized void countCreate(){
        for(int i=0;i<5;i++){
          System.out.println(FinalCount.y);
          --FinalCount.y;
          }
      }}
    class Thread1 extends Thread{  public void run(){
        FinalCount.countCreate1();
      }
    }
    class Thread2 extends Thread{  public void run(){
        FinalCount.countCreate();
      }
    }
    public class TestThread {
      public static void main(String[] args){
        System.out.println(FinalCount.y);
        Thread1 thread1a=new Thread1();
        Thread1 thread1b=new Thread1();
        Thread2 thread2a=new Thread2();
        Thread2 thread2b=new Thread2();
        thread1a.start();
        thread1b.start();
        thread2a.start();
        thread2b.start();
      }}
    可惜输出如下:
    112345678910111098765432看来各位大侠还要劳神一下?谢谢!!!
      

  3.   

    to ajiao:
    这不关并发访问的事,所以同步不同步无所谓。
    其实问题出在楼主对线程的运行不太理解。
    他希望程序按 thread1a,thread1b,thread2a,thread2b 这样的顺序运行。
    其实这是很不可靠的。多线程程序的运行顺序是不可预测的。
    这个程序的结果看上去应该更怪,因为线程中的循环很小,在一个时间片
    中就可完成。循环放大到一个时间片不能完成时,结果会更怪。
      

  4.   

    class FinalCount{
      public static int y=1;
      public static int addCnt=0;
      public static int subCnt=0;
      public static int expectedCnt=10;
      public static synchronized void countCreate1(){
        for(int i=0;i<5;i++){
         System.out.println(Thread.currentThread().getName());//add watch
          //if(i==0){
          System.out.println(y);
          //}
          ++y;//改
          addCnt++;
          if(addCnt==expectedCnt){//print the last value
           System.out.println("the last add result,gosh---->");
           System.out.println(y);
          }
        }
      }
      public static synchronized void countCreate(){
        for(int i=0;i<5;i++){
         System.out.println(Thread.currentThread().getName());//add watch
          //System.out.println(FinalCount.y);//你为什么要放在这那?你要想打印1么?呵呵
          --y;//改!
          System.out.println(y);
          }
      }}
    class Thread1 extends Thread{
    public Thread1(String name){//add name
    super(name);
    }
      public void run(){
        FinalCount.countCreate1();
      }
    }
    class Thread2 extends Thread{
    public Thread2(String name){//add name
    super(name);
    }
      public void run(){
        FinalCount.countCreate();
      }
    }
    public class TestThread {
      public static void main(String[] args){
        //System.out.println(FinalCount.y);//这条语句极其好啊,让我极其恼火,呵呵
        Thread1 thread1a=new Thread1("thread1a");
        Thread1 thread1b=new Thread1("thread1b");
        Thread2 thread2a=new Thread2("thread2a");
        Thread2 thread2b=new Thread2("thread2b");
        thread1a.start();
        thread1b.start();
        thread2a.start();
        thread2b.start();
      }}老弟啊,你的算法,甚至可以说想法有些不妥吧,呵呵,让我改起来很恼火哦,另外,你的线程认知不够哦,多多努力.............
      

  5.   

    package testthread;class FinalCount{
      public static int y=1;
      public static int addCnt=0;
      public static int subCnt=0;
      public static int expectedCnt=10;
      public static synchronized void countCreate1(){
        for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName());//add watch
          //if(i==0){
          System.out.println(y);
          //}
          ++y;//改
          addCnt++;
          if(addCnt==expectedCnt){//print the last value
                  System.out.println("the last add result,gosh---->");
                 System.out.println(y);
          }
        }
      }
      public static synchronized void countCreate(){
        for(int i=0;i<5;i++){
                System.out.println(Thread.currentThread().getName());//add watch
          --y;
          System.out.println(y);
          }
      }}
    class Thread1 extends Thread{
            public Thread1(String name){//add name
                    super(name);
            }
      public void run(){
        FinalCount.countCreate1();
      }
    }
    class Thread2 extends Thread{
            public Thread2(String name){//add name
                    super(name);
            }
      public void run(){
        FinalCount.countCreate();
      }
    }
    public class TestThread {
      public static void main(String[] args){
        Thread1 thread1a=new Thread1("thread1a");
        Thread1 thread1b=new Thread1("thread1b");
        Thread2 thread2a=new Thread2("thread2a");
        Thread2 thread2b=new Thread2("thread2b");
        thread1a.start();
        thread1a.setPriority(10);
        thread1b.start();
        thread1b.setPriority(8);
        thread2a.start();
        thread2b.start();
        thread2b.setPriority(3);
      }}
    结果如下
    thread1a1thread1a2thread1a3thread1a4thread1a5thread1b6thread1b7thread1b8thread1b9thread1b10the last add result,gosh---->11thread2a10thread2a9thread2a8thread2a7thread2a6thread2b5thread2b4thread2b3thread2b2thread2b1遵照各位大哥的意见,我作如上修改,,是希望输出。我的想法是这样的,不知对不对
    1:用同步控制对y的访问,这样他属于同一线程,别的线程不能访问他,这样他能递增。
    2:用线程优先极控制程序执行。
    不知以上对不对,请各位大哥指正,也好快快结贴,谢谢!!!
      

  6.   

    那么多位大哥给你提了醒,你还是没能够领悟,呵呵,需要好好看看书哦
    1.synchronized同步的作用是,保证任何时间,只有一个线程能访问同步对象中被synchronized的方法。这样做的目的在于,当多个线程要对同一资源做出修改或者读取时(比如你这里的y),只有一个时间只有一个线程在能够访问这些同步方法。这样做是为了保证数据操作的原子性,原子性的意思就是,当我要操作这个数据时,虽然可能有几个步骤,但是在这些步骤当中,我的操作必须保证连贯,期间不被其他人(这里指其他线程)打扰。因而我们使用synchronized来对数据敏感方法全部保护起来,来保证操作的安全性。2.线程优先级是可以设定的,但是只能从概率上对线程的执行进行了分配。比如a线程是最大优先级别,b线程级别较低,在一个较长的时间范围内,可以保证a的执行次数要多于b。但是在任何一个时间点,谁被虚拟机调用却不是固定的。因而,你这个程序不能说能够完全确保你所要达到的输出,因为各个线程执行的先后是不固定的,这里1a与1b只是说执行任务时间短,在2a与2b启动时已经完成了run中的执行体,对于2a与2b之间,为什么能够显示2a完之后才到2b,就是因为这个原因,因为线程在启动后很快死亡,在这期间不存在争抢。3.为了让你得到感性与理性的认识,这里你运行我提供的例子:public class ReadDirtyTest{
    public static void main(String[] args){
    ReadWrite rw=new ReadDirtyTestThreadSafe();
    new WriteThread(rw).start();
    new ReadThread(rw).start();
    }}interface ReadWrite{
    public void addReadMe();
    public void readReadMe();
    public int getReadMe();
    //public void reSetReadMe();
    }//public class ReadDirtyTest{
    class ReadDirtyTestThreadSafe implements ReadWrite{
    private int readMe;

    /*public static void main(String[] args){
    ReadDirtyTest test=new ReadDirtyTest();
    new WriteThread(test).start();//&acute;&acute;&frac12;¨&sup2;&cent;&AElig;&ocirc;&para;&macr;&ETH;&acute;&Iuml;&szlig;&sup3;&Igrave;
    new ReadThread(test).start();//&acute;&acute;&frac12;¨&sup2;&cent;&AElig;&ocirc;&para;&macr;&para;&Aacute;&Iuml;&szlig;&sup3;&Igrave;
    }*/


    synchronized public void addReadMe(){
    //&Atilde;&iquest;&acute;&Icirc;add&sup2;&Ugrave;×÷&para;&Ocirc;readme&Ouml;&acute;&ETH;&ETH;&Aacute;&frac12;&acute;&Icirc;&Agrave;&Ucirc;&frac14;&Oacute;,
    System.out.println("Trans1:begin adding readme value==============================");
    //&micro;&Uacute;&Ograve;&raquo;&acute;&Icirc;&Agrave;&Ucirc;&frac14;&Oacute;
    readMe++;
    //&acute;ò&Oacute;&iexcl;&micro;&Uacute;&Ograve;&raquo;&acute;&Icirc;&Agrave;&Ucirc;&frac14;&Oacute;&ordm;ó&micro;&Auml;&Aacute;&Ugrave;&Ecirc;±&Ouml;&micro;
    System.out.println("the temporary readme value now is " + readMe);
    try{
    //&Ecirc;&sup1;&micro;±&Ccedil;°&ETH;&acute;&Iuml;&szlig;&sup3;&Igrave;&ETH;&Yacute;&Atilde;&szlig;,&cedil;&oslash;&para;&Aacute;&Iuml;&szlig;&sup3;&Igrave;&Igrave;&Uacute;&sup3;&ouml;&Ocirc;&Euml;&ETH;&ETH;&Ecirc;±&frac14;&auml;
    Thread.currentThread().sleep(1000);
    }catch(InterruptedException x){
    System.out.println("InterruptedException is thrown out...");
    }
    //&micro;&Uacute;&para;&thorn;&acute;&Icirc;&Agrave;&Ucirc;&frac14;&Oacute;
    readMe++;
    //&acute;ò&Oacute;&iexcl;×&icirc;&Ouml;&Otilde;&ETH;&THORN;&cedil;&Auml;&ordm;ó&micro;&Auml;&Ouml;&micro;
    System.out.println("the expected readme value now is " + readMe);
    System.out.println("Trans2:finish adding readme value==============================");

    }

    synchronized public void readReadMe(){
    //&para;&Aacute;&micro;±&Ccedil;°readme&micro;&Auml;&Ouml;&micro;,&Oacute;&ETH;&iquest;&Eacute;&Auml;&Uuml;&para;&Aacute;&sup3;&ouml;&micro;&Auml;&Ecirc;&Ccedil;addReadMe&sup2;ú&Eacute;ú&micro;&Auml;dirty&Ouml;&micro;
    System.out.println("read readme vlaue=" + readMe + "***Maybe Dirty Read***");
    try{
    Thread.currentThread().sleep(50);
    }catch(InterruptedException x){
    System.out.println("InterruptedException is thrown out...");
    }

    }

    synchronized public int getReadMe(){
    return readMe;
    }

    }class WriteThread extends Thread{
    //ReadDirtyTest test;
    ReadWrite test;
    //public WriteThread(ReadDirtyTest test){
    public WriteThread(ReadWrite test){
    super("WriteThread");
    this.test=test;
    }
    public void run(){
    //while(test.readMe<5){
    while(test.getReadMe()<5){
    test.addReadMe();
    }
    }
    }class ReadThread extends Thread{
    //ReadDirtyTest test;
    ReadWrite test;
    //public ReadThread(ReadDirtyTest test){
    public ReadThread(ReadWrite test){
    super("ReadThread");
    this.test=test;
    }
    public void run(){
    //while(test.readMe<5){
    while(test.getReadMe()<5){
    test.readReadMe();
    }
    }
    }这是正确的程序,当你把标有synchronized的方法去掉synchronized标识后,再运行一遍看看,思考一遍,你会有收益的。
      

  7.   

    谢谢大哥:
           可是如何实现如下目标,i初始值为1,用前两个线程使i递增,后两个线程使i递减,输出i的值如下:1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1,这是我在一家中国目前排名前5的一家软件公司应聘的题目。这样看来似乎无解,因为不能百分之百的使前两个线程快于后两个线程,郁闷啊!!!
      

  8.   

    根本就不需要设置线程优先权,前两个线程肯定是优于后两个。
    运行的顺序肯定是按他们定义的先后顺序。
    因为这四个线程的run函数都是访问类FinalCount的synchronized函数,
    类FinalCount的机锁同时只能有一个线程访问,当第一个线程thread1a在运行时,
    其它的3个线程由于不拥有类FinalCount的机锁,因此只能等待。
    (即使在第一个线程里循环1万次,或者sleep(1000),cpu也不会把运行权交给其它公用一个机锁的线程,除非你调用了对象的wait())
      

  9.   

    至于要打出  1 2 3 4 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1,你只需要在countCreate1()
    里面加入一个判断,当y被加到10的时候,就停止。相应的在countCreate()中加入一个判断,
    防止y被减成0
    public static synchronized void countCreate1(){
        for(int i=0;i<5;i++){
          if(y==10)
            System.out.println(y);
          else
            System.out.println(y++);
          }  }public static synchronized void countCreate(){
        for(int i=0;i<5;i++){
                
           System.out.println(y);
           if(y!=1)
              --y;
          
          }
      }
      

  10.   

    To ajiao:
           这个到不一定,你说得锁定,只是在同一线程的内部运行的时候,从一个线程到另一线程时候,比如线程一用完,可能线程三开始运行,而不是线程2,所以结果有时会是:
          1 2 3 4 5 6 5 4 3 2 1 0 -1 -2 -3 -4 -3 -2 -1 -0 1
          这个结果有时换一台电脑一下就出来,试一试就知道。我就运行出来过,大哥也可以试一试,jxspace说得没错。可能这个问题是不是要换一种思路???
      

  11.   

    ajiao说的方法可行。
    另外,最正确也是最合理的方式是采用信号量来实现,但现在太晚了,明天我来将其实现,呵呵,好题目,精彩啊。
      

  12.   


    public class Driver {    public static volatile int j=1;    public static void main(String[] args){
            IncrThread it1=new IncrThread();
            IncrThread it2=new IncrThread();
            DecrThread dt1=new DecrThread();
            DecrThread dt2=new DecrThread();
            it1.start();
            it2.start();
            dt1.start();
            dt2.start();    }    class IncrementThread extends Thread{
            public void run(){
                for(int i=0;i<5;i++){
                    System.out.println(j++);
                }
            }
        }    class DecrementThread extends Thread{
            public void run(){
                for(int i=0;i<5;i++){
                    System.out.println(--j);
                }
            }
        }
    }
      

  13.   

    the posted program gives you exactly what you want. but you have to know that it's not reliable. as a warning, when doing multi-threading programming, don't
    trust the thread scheduler. if you want more details about threading and how JVM
    scheduler works, i recommamd that you read the JVM specification (you can download a free copy from sun's website). last but not the least, don't predict
    the sequence in which your threads will run, it's totally unpredictable.
      

  14.   

    To tiger999:
              大哥的例子小弟在jbuilder7下不能运行,提示为:
              'this' can not be referenced from a static context at line 10.
              (已经修改了不匹配的类名:DecrementThread->DecrThread.IncrementThread->
               IncrThread)????
      

  15.   

    喂喂,看不下去了,这么简单的问题,讨论这么久,
    搂主的主要问题在于没有对要操作的数据设置排它锁,笨
    以下程序就可以完成你的要求了,看吧
    /**
     * <p>Title: </p>
     * <p>Description: </p>
     * <p>Copyright: Copyright (c) 2003</p>
     * <p>Company: </p>
     * @author unascribed
     * @version 1.0
     */
    class FinalCount{
      public static int y=1;
      public static synchronized void increase(){
       y++;
      }
      public static synchronized void decrease(){
       y--;
      }
    }
    class Thread1 extends Thread{
      public void run(){
        for(int i=0;i<5;i++){
          FinalCount.increase();
          System.out.println(FinalCount.y);
        }
      }
    }
    class Thread2 extends Thread{
      public void run(){
        for(int i=0;i<5;i++){
          FinalCount.decrease();
          System.out.println(FinalCount.y);
        }
      }
    }
    public class test {
      public static void main(String[] args){
        System.out.println(FinalCount.y);
        Thread1 thread1a=new Thread1();
        Thread1 thread1b=new Thread1();
        Thread2 thread2a=new Thread2();
        Thread2 thread2b=new Thread2();
        thread1a.start();
        thread1b.start();
        thread2a.start();
        thread2b.start();
      }}
    输出结果为:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1这样行了吧?
      

  16.   

    今天仔细看了aJiao老弟的说法,发现了极大的错误ajiao said:
    1.根本就不需要设置线程优先权,前两个线程肯定是优于后两个。
    2.运行的顺序肯定是按他们定义的先后顺序。
    3.因为这四个线程的run函数都是访问类FinalCount的synchronized函数,
    类FinalCount的机锁同时只能有一个线程访问,当第一个线程thread1a在运行时,
    其它的3个线程由于不拥有类FinalCount的机锁,因此只能等待。
    (即使在第一个线程里循环1万次,或者sleep(1000),cpu也不会把运行权交给其它公用一个机锁的线程,除非你调用了对象的wait())问题1存在的问题是,“前两个线程肯定是优于后两个”,它们是被最先start,肯定是被优先“考虑”执行的,但是并不代表它们优先级别高,我前面说过,优先级不是先后的问题,而是在一个时间范围内被执行多少的概率问题。问题2存在的问题是,前面1提到“肯定是被优先“考虑”执行的”,仅仅是“优先考虑”,而不是说一定是这个顺序。问题3在表达上面存在模糊之处,含糊的地方是“即使在第一个线程里循环1万次”,不应该说在线程里循环,应该是在FinalCount类方法中CountCreate里头循环一万次这种说法才确切(如果按照你这种改法的话--就是把for循环放到FinalCount的CountCreate里头),在CountCreate里无论循环多少次还是sleep,只要没有走出这个被synchronized的方法体,机锁是不会被释放的。为了形象一些,可以对程序做出这样的改动:#######运行更改一:
    public static synchronized void countCreate(){
       try{
       System.out.println("I will sleep....");
       Thread.currentThread().sleep(1000);
       }catch(Exception x){
       }
        for(int i=0;i<5;i++){
          System.out.println(FinalCount.y);
          --FinalCount.y;
          }
      }
    结果是:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    I will sleep....
    11
    10
    9
    8
    7
    I will sleep....
    6
    5
    4
    3
    2
    #######运行更改二:
    class Thread1 extends Thread{  public void run(){
       try{
       System.out.println("i will sleep...");
       sleep(50);
       }catch(Exception x){
       }
        FinalCount.countCreate1();
      }
    }结果:
    i will sleep...
    i will sleep...
    1
    0
    -1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -8
    -7
    -6
    -5
    -4
    -3
    -2
    -1
    0最后应该指出的是,诚然如 tiger999(不吃肉的老虎) 所说,是因为楼主老弟对线程的理解还不够准确和深刻,将for循环放入synchronized中并非一个灵活而且正确的解决方式,我将给出一个解决方案,如下帖。
      

  17.   

    在提出我的解决方法前,先看看redsnakecao(曹) 的解法,如果,我们在main方法中稍微做一下调整,来看看会有什么结果:public class test {
      public static void main(String[] args){
        System.out.println(FinalCount.y);
        Thread1 thread1a=new Thread1();
        Thread1 thread1b=new Thread1();
        Thread2 thread2a=new Thread2();
        Thread2 thread2b=new Thread2();
        thread2a.start();//这里将decrease 线程提前
        thread1a.start();
        thread1b.start();
        
        thread2b.start();
      }}运行结果是:
    1
    0
    -1
    -2
    -3
    -4
    -3
    -2
    -1
    0
    1
    2
    3
    4
    5
    6
    5
    4
    3
    2
    1这种改法是很极端的改法,就是模拟了一种状态,两个加线程被block住(因为jvm的原因,几率虽然很小),thread2a被率先执行的这么一种情况。另外也可以这样改:
    class Thread1 extends Thread{
      public void run(){
       try{
         System.out.println("Sorry, I am blocked by unknown reason,damn JVM, sun can not ensure it...");
         sleep(50);
        
        }catch(Exception x){
        
        }
        for(int i=0;i<5;i++){
        
          FinalCount.increase();
          System.out.println(FinalCount.y);
        }
      }
    }
      

  18.   

    这是改进过后的++程序代码:class FinalCount{

      private int y=1;
      
      private int maxValue=10;//default max value
      private int minValue=1;//default min value
      
      private boolean releaseIncThreadFlag=false;//release flag for decrease thread
      private boolean releaseDecThreadFlag=false;//release flag for increase thread
      
      private boolean arriveMax=false;
      
      public FinalCount(){
      
      }
      
      public FinalCount(int max,int min){
       //if it is valid max-min releationship, override the default scenary
       if(max>min){
       maxValue=max;
       minValue=min;
       y=min;
       }
      }  public synchronized void increase(){
       //limitation control
       if(y==maxValue)
       return;
       printY();
       y++;
       //increase to the max value, sets the control parameters and
       //notify all waiting threads
       if(y==maxValue){
       releaseIncThreadFlag=true;
       arriveMax=true;
       printY();//print the top value
       notifyAll();
       }
      }
      public synchronized void decrease(){
       //limitation control
       if(y==minValue)
       return;
       y--;
       printY();
       //decrease to the min value, sets the control parameters and
       //notify all waiting threads
       if(y==minValue){
       releaseDecThreadFlag=true;
       arriveMax=false;
       notifyAll();
       }
      }
      
      private void printY(){
       System.out.println("thread name=" + Thread.currentThread().getName());
       System.out.println(y);
      }
      //wait() control method
      public synchronized boolean isArriveMaxValue(){
       return arriveMax;
      }
      //wait() control method
      public synchronized boolean isReleaseIncThread(){
       return releaseIncThreadFlag;
      }
      //wait() control method
      public synchronized boolean isReleaseDecThread(){
       return releaseDecThreadFlag;
      }
      //get the max value for loop count
      public int getMaxValue(){
       return maxValue;
      } 
    }
    class IncThread extends Thread{
      FinalCount count;
      
      public IncThread(String name,FinalCount count){
       super(name);
       this.count=count;
      }
      
      public void run(){
      
        for(int i=0;i<count.getMaxValue();i++){
          synchronized(count){
           //for balance consideration and release increase thread...
       while(count.isArriveMaxValue() & !count.isReleaseIncThread()){
       try{
       count.wait();
       }catch(Exception x){
      
       }
       }
         }
     //if need to release current thread
         if(count.isReleaseIncThread())
          break;
         count.increase();
          
        }
        
        //release prompt:
        System.out.println("====== Thread(" + getName() + ") is released....");
        
      }
    }
    class DecThread extends Thread{
      FinalCount count;
      
      public DecThread(String name,FinalCount count){
       super(name);
       this.count=count;
      }
      
      public void run(){
      
           for(int i=0;i<count.getMaxValue();i++){
             synchronized(count){
              //when still not arrive at the max value,or still not release, waiting...
       while(!count.isArriveMaxValue() & !count.isReleaseDecThread()){
       try{
       count.wait();
       }catch(Exception x){
      
       }
       }
         }
         if(count.isReleaseDecThread())
          break;
          count.decrease();
        }
        
        System.out.println("====== Thread(" + getName() + ") is released....");
      }
    }
    public class Test3 {
      public static void main(String[] args){
       FinalCount fc=new FinalCount();
        //FinalCount fc=new FinalCount(30,1);
        IncThread incThread1=new IncThread("incThread1",fc);
        IncThread incThread2=new IncThread("incThread2",fc);
        IncThread incThread3=new IncThread("incThread3",fc);
        
        IncThread incThread4=new IncThread("incThread4",fc);
        DecThread decThread1=new DecThread("decThread1",fc);
        DecThread decThread2=new DecThread("decThread2",fc);
        DecThread decThread3=new DecThread("decThread3",fc);
        decThread2.start();//pay attention here!
        decThread3.start();
        incThread2.start();
        
        incThread1.start();
        incThread4.start();
        
        incThread3.start();
        decThread1.start();
      }}运行结果:
    ===============================thread name=incThread2
    1
    thread name=incThread2
    2
    thread name=incThread2
    3
    thread name=incThread2
    4
    thread name=incThread1
    5
    thread name=incThread4
    6
    thread name=incThread3
    7
    thread name=incThread1
    8
    thread name=incThread4
    9
    thread name=incThread4
    10
    ====== Thread(incThread3) is released....
    thread name=decThread2
    9
    thread name=decThread3
    8
    thread name=decThread1
    7
    ====== Thread(incThread4) is released....
    ====== Thread(incThread2) is released....
    thread name=decThread2
    ====== Thread(incThread1) is released....
    6
    thread name=decThread3
    5
    thread name=decThread1
    4
    thread name=decThread1
    3
    thread name=decThread2
    2
    thread name=decThread1
    1
    ====== Thread(decThread1) is released....
    ====== Thread(decThread2) is released....
    ====== Thread(decThread3) is released....======================================
    这个解决方案更显得灵活,也能够完全确保数值由1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1这种顺序输出,而不论加减线程启动的先后,也可以将阈值设定在非1,10的任一一个范围,消除了不确定性,也充分利用了java提供的线程控制机制。如,可以这样改:
    main函数中:
    FinalCount fc=new FinalCount(13,12);
    ...
    运行结果:
    thread name=incThread2
    12
    thread name=incThread2
    13
    thread name=decThread2
    12
    ====== Thread(decThread2) is released....
    ====== Thread(decThread3) is released....
    ====== Thread(incThread2) is released....
    ====== Thread(incThread1) is released....
    ====== Thread(incThread4) is released....
    ====== Thread(incThread3) is released....
    ====== Thread(decThread1) is released....
    这个例子是使用java线程的一个非常好的范例,也是我为什么在上边的帖子中提到说这个问题精彩的原因所在。
      

  19.   

    下面的程序应该是可靠的,你可任意调换线程起动次序,结果都一样。public class Test {
            public static void main(String[] args){            SharedData sd=new SharedData();            IncrementThread it1=new IncrementThread(sd);
                IncrementThread it2=new IncrementThread(sd);
                DecrementThread dt1=new DecrementThread(sd);
                DecrementThread dt2=new DecrementThread(sd);            dt1.start();
                it1.start();
                dt2.start();
                it2.start();
            }
    }  class IncrementThread extends Thread{
           private SharedData sd=null;
           public IncrementThread(SharedData sd){
               this.sd=sd;
           }       public void run(){           for(int i=0;i<500;i++){
                   if(sd.whosRun==sd.INCREMENT_RUN)
                      System.out.println(sd.j++);
                   if(sd.j==1001){
                      sd.whosRun=sd.DECRMENT_RUN;
                   }
               }       }
      } class DecrementThread extends Thread{
           private SharedData sd=null;
           public DecrementThread(SharedData sd){
               this.sd = sd;
           }
           public void run(){
              synchronized(sd){
               while(sd.whosRun!=sd.DECRMENT_RUN){
                  try{
                     sd.wait();
                  }catch(Exception e){}
               }             for(int i=0;i<500;i++){
                     System.out.println(--sd.j);
                 }
              }
           }}class SharedData extends Thread{
        public int j=1;
        public final int INCREMENT_RUN=0;
        public final int DECRMENT_RUN=1;
        public volatile int whosRun=0;
        public boolean running=true;    public SharedData(){
            this.setDaemon(true);
        }
        public void run(){        while(true){
              if(whosRun==INCREMENT_RUN)
                   notifyAll();
            }
        }
    }
      

  20.   


    To tiger999(不吃肉的老虎)大哥:
          我运行你的程序,得出结果如下,只有递增过程,无递减。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
      

  21.   

    to testhu():
    不是提醒过你把 synchronized( sd ) 去调吗!!!