class MyThread implements Runnable
{
private int ticket = 20 ;
public void run(){
for(int i=0;i<300;i++){

if(this.ticket>0){
try{
Thread.sleep(1000) ;
}catch(Exception e){}
// 表示还有票,可以卖
System.out.println(Thread.currentThread().getName()+" --> 卖票:"+(ticket--)) ;
}
}
}
};
public class Test
{
public static void main(String args[]){
MyThread mt = new MyThread() ;
Thread t1 = new Thread(mt) ;
Thread t2 = new Thread(mt) ;
Thread t3 = new Thread(mt) ;

t1.start() ;
t2.start() ;
t3.start() ;

}
};运行结果:Thread-0 --> 卖票:20
Thread-1 --> 卖票:19
Thread-2 --> 卖票:18
Thread-0 --> 卖票:17
Thread-1 --> 卖票:16
Thread-2 --> 卖票:15
Thread-0 --> 卖票:14
Thread-1 --> 卖票:13
Thread-2 --> 卖票:12
Thread-0 --> 卖票:11
Thread-1 --> 卖票:10
Thread-2 --> 卖票:9
Thread-0 --> 卖票:8
Thread-1 --> 卖票:7
Thread-2 --> 卖票:6
Thread-1 --> 卖票:5
Thread-0 --> 卖票:4
Thread-2 --> 卖票:3
Thread-1 --> 卖票:2
Thread-0 --> 卖票:1
Thread-2 --> 卖票:0
Thread-1 --> 卖票:-1
结果只是最后两行信息有误,不合常理。我的疑问:既然各个线程都有时间延迟(休眠),为什么运行结果中没出现卖同一张票的情况呢?比如说,Thread-2在卖9号时休眠,此时Thread-1或者Thread-0看到的不是(ticket--)后的8号票-->应该也是9号票,这样他们就会卖出同一张票,是吗?也许是我没理解,远高手指点  感激不尽!另外,回答了上一问之后,再问:如何编程实现多个线程卖出同一张票的情况呢?(就是编一个不合常理的程序)

解决方案 »

  1.   

    你的这个会出现卖同一张票的情况,多运行几次就出现了,每次的结果都不一样你把private int ticket = 20 ; 
    改大,出现的几率就会变大
      

  2.   

    1.既然各个线程都有时间延迟(休眠),为什么运行结果中没出现卖同一张票的情况呢?
    因为所有Thread都对应的是一个Runable
    2.Thread-2 --> 卖票:0 
    Thread-1 --> 卖票:-1 结果只是最后两行信息有误,不合常理。 因为在if(this.ticket>0)这里的时候,没有同步保护./**
     * 
     */
    package thread;/**
     * Title: Test.java
     * Description: 
     * 2009-7-12 下午03:13:11
     * @author LiN
     */
    public class Test {
    static int ticket =200;

    public static void main(String[] args) {
    Thread t1 = new Thread(){
    public void run() {
    while(true){
    if(Test.ticket>0){ 
    System.out.println(Thread.currentThread().getName()+" come in");
    try{ 
    Thread.sleep(200) ; 
    }catch(Exception e){} 
    // 表示还有票,可以卖 
    System.out.println(Thread.currentThread().getName()+" --> 卖票:"+(Test.ticket--)) ; 
    } else
    break;
    }
    }
    };
    Thread t2 = new Thread(){
    public void run() {
    while(true){
    if(Test.ticket>0){ 
    System.out.println(Thread.currentThread().getName()+" come in");
    try{ 
    Thread.sleep(1000) ; 
    }catch(Exception e){} 
    // 表示还有票,可以卖 
    System.out.println(Thread.currentThread().getName()+" --> 卖票:"+(Test.ticket--)) ; 
    } else
    break;
    }
    }
    };
    Thread t3 = new Thread(){
    public void run() {
    while(true){
    if(Test.ticket>0){ 
    System.out.println(Thread.currentThread().getName()+" come in");
    try{ 
    Thread.sleep(1000) ; 
    }catch(Exception e){} 
    // 表示还有票,可以卖 
    System.out.println(Thread.currentThread().getName()+" --> 卖票:"+(Test.ticket--)) ; 
    } else
    break;
    }
    }
    };

    t1.start();
    t2.start();
    t3.start();
    }
    }LZ看下输出,就明白为什么会出现0和-1了
      

  3.   


    哦,我似乎有点理解了,但是,按我说的那样:比如说,Thread-2在卖9号时休眠,此时Thread-1或者Thread-0看到的不是(ticket--)后的8号票-->应该也是9号票,这样他们就会卖出同一张票,是吗?
      

  4.   

    楼上那么多怎么都在说别人没有同步呢?
    搞清楚,楼主是故意没有同步,是在做实验!!!上面我已经说过了,你多运行几次,自然就会出现卖同一张票的情况了。
    出现Thread-2 --> 卖票:0 
    Thread-1 --> 卖票:-1 
    也是有一定几率的,并不是一定会出现这个结果
    出现的原因是ticket==1的时候this.ticket>0 一个thread进入了if,开始休眠1000ms
    这个时候,ticket还没有--,还是1,另一个线程也符合this.ticket>0,所以也开始执行if里的代码当一个线程执行完之后,ticket--,变成了0,这个时候另外一个线程休眠完毕,执行ticket--,就变成了-1
      

  5.   

    楼上说的很有道理,卖了票0和卖了票1就是这个原因。但是因为休眠的时间太长,几乎使得出现卖票0和卖票1成为必然。
    如果把程序改一下会好一些
    class MyThread implements Runnable 

    private int ticket = 20 ; 
    public void run(){ 
    for(int i=0;i <300;i++){ 
    try{ 
    Thread.sleep(1000) ; 
    }catch(Exception e){} 

    if(this.ticket>0){ 
    // 表示还有票,可以卖 
    System.out.println(Thread.currentThread().getName()+" --> 卖票:"+(ticket--)) ; 



    }; 
    public class Test 

    public static void main(String args[]){ 
    MyThread mt = new MyThread() ; 
    Thread t1 = new Thread(mt) ; 
    Thread t2 = new Thread(mt) ; 
    Thread t3 = new Thread(mt) ; t1.start() ; 
    t2.start() ; 
    t3.start() ; } 
    }; 
    这样就不会出现上面的情况了,同样是没有用到同步处理。楼主的意思好像是想让一个线程在休眠的时候让另一个线程在这个时间段内修改共享变量的值。这其实是错误的。
    卖出同一张票的情况只在以下情况下发生:
       当一个线程执行(ticket--;)时,当这个线程执行到一半的时候(只是将ticket值读出,未进行++操作,或者进行了++操作,未写回),系统分配给这个线程的时间被用完了,这个线程被迫停止执行,系统去执行另一个线程,这个线程读到的ticket的值与上一个线程读到的值是完全一样的,所以就出现了卖一张票的情况。因为ticket--操作只占用的系统时间非常短,所以即使不进行同步处理一般也不会出现卖一张票的情况。如果楼主真想出现那么建议将ticket--;操作改为以下代码:      int temp = ticket;
         Thread.sleep(10);
         temp =temp --;
         ticket = temp;
    或者:
         int temp = ticket;
         temp =temp --;
         Thread.sleep(10);     
         ticket = temp;