for(int k = 10 ;k>0;){}简单来说,线程t1,执行10次 k=10,k=9,k=8...
线程t2,执行10次 k=10,k=9,k=8...楼主加断点DEBUG下,自己看比较清楚

解决方案 »

  1.   

    你这样肯定有问题啊,每个线程都执行一个单独的实例。 就是说你线程一里面的k和你线程二里面的k根本就不是一个。
    你要把k放到一个公共区里面,而且还要加锁
      

  2.   

    你这个k==0 应该放下面吧,不然没票打印不出。
      public void run() {
         for(;k>0;){
                System.out.println("当前线程["+Thread.currentThread().getName()+"]卖出票,还有的数量:"+(k--));
                if( k == 0 )
                    System.out.println("当前线程["+Thread.currentThread().getName()+"]没票了");
            }
        }都是线程-2工作,被卖的数量没错!---->  这个你多运行几次会发现有1 的线程 。
      

  3.   

    因为k在for循环中时,是局部变量,并不是两个线程共享的,而是独立的。而第一情况k是实例变量,两个线程的Runnable实例对象相同,访问的是同一个实例变量k。
      

  4.   

    能出现第一种情况真是侥幸k为成员变量时会出现资源竞争的问题,此时需要对共享资源进行同步(synchronized or lock)建议看一下线程状态和CPU调度相关资料
      

  5.   

    哦,看错了。用的一个对象,你把k改成1000再试一下呢也就是说,那个k变了?
    可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?
    这就是我问题的根本想问的!
      

  6.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?
      

  7.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?每个线程都有自己的栈,用来存储线程中的本地变量,也就是变量k,t1和t2分别拥有自己的栈信息,
    分别保存了本地变量k的副本,互不影响,所以各打印10次
      

  8.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题
    当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,
    此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符
      

  9.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题
    当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,
    此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符
    如你所说的话,那么,既然t1改变了,t2接下来用被改变的值,那么,为什么加上一句try{t.sleep(time)}catch(...){...}就又有可能t1和t2拿到相同的值呢?
      

  10.   

    哦,看错了。用的一个对象,你把k改成1000再试一下呢也就是说,那个k变了?
    可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?
    这就是我问题的根本想问的!
    两个线程引用的同一个任务对象 mr,所以k中共用的。然后你run方法肯定是每个线程都有一个自己的run方法,你可以在run里面定义一个自加变量测一下,看一下每个线程是不是的变量是不是独立的。
      

  11.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题
    当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,
    此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符
    如你所说的话,那么,既然t1改变了,t2接下来用被改变的值,那么,为什么加上一句try{t.sleep(time)}catch(...){...}就又有可能t1和t2拿到相同的值呢?Thread.sleep() 会让出当前线程让其它线程执行,如果此时k=8,t1执行到了
    System.out.println(........k-- );此时t1 sleep(),t2执行了 k--,此时打印
    值为7,此时t1醒了继续执行,于是k--,打印了值为 7,而此时k的值为6
      

  12.   


    1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
    2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题
    当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,
    此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符
    如你所说的话,那么,既然t1改变了,t2接下来用被改变的值,那么,为什么加上一句try{t.sleep(time)}catch(...){...}就又有可能t1和t2拿到相同的值呢?Thread.sleep() 会让出当前线程让其它线程执行,如果此时k=8,t1执行到了
    System.out.println(........k-- );此时t1 sleep(),t2执行了 k--,此时打印
    值为7,此时t1醒了继续执行,于是k--,打印了值为 7,而此时k的值为6你把 k-- 换成 --k,看是否还可打印相同的值
      

  13.   


    如你所说,的话,好像是这样,但是不是。
    首先, --k也能有相同的数字。
    其次,我代码大概是public void run(){
     for(;k>0;)
      system.out.println(........ --k);
    }
    int k = 10 ;
      

  14.   


    如你所说,的话,好像是这样,但是不是。
    首先, --k也能有相同的数字。
    其次,我代码大概是public void run(){
     for(;k>0;)
      system.out.println(........ --k);
    }
    int k = 10 ;错了,我忘了 -- ++操作不是原子操作,可能会出现重复值,sorry,假设这里用java的原子操作,那么就不会出现相同的值。
    我说的意思就是,CPU会给每个就绪的线程分配时间片,如果一个线程的时间片到期,就会轮到其他线程执行,如果在线程切换的时候刚好改变了某些资源的状态,就会出现数据不一致的情况,这个时候就需要对资源进行同步,保证数据的一致性。
      

  15.   

    表示你第一种写法得出的结果简直是侥幸。第一种写法没错,只不过运行结果让你迷惑了。试试下面的写法,让当前线程先sleep500毫秒,就能得到你要的效果了。public class Thread1 {
    public static void main(String[] args) {
    MyRunnable mr = new MyRunnable() ;
    Thread t1 = new Thread(mr,"线程-1") ;
    Thread t2 = new Thread(mr,"线程-2") ;
    t1.start();
    t2.start();
    }
    }
    class MyRunnable implements Runnable{
    @Override
    public void run() {
    for(;k>0;){
    if( k == 0 )
    System.out.println("当前线程["+Thread.currentThread().getName()+"]没票了");
    System.out.println("当前线程["+Thread.currentThread().getName()+"]卖出票,还有的数量:"+(k--));
    try {
    Thread.currentThread().sleep(500);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }
    }
    private int k = 10;
    }
      

  16.   

    public class Thread1 {
    public static void main(String[] args) {
    MyRunnable mr = new MyRunnable() ;
    Thread t1 = new Thread(mr,"线程-1") ;
    Thread t2 = new Thread(mr,"线程-2") ;
    t1.start();
    t2.start();
    }
    }
    class MyRunnable implements Runnable{
    @Override
    public void run() {
    for(;k>0;){
    if( k == 0 )
    System.out.println("当前线程["+Thread.currentThread().getName()+"]没票了");
    System.out.println("当前线程["+Thread.currentThread().getName()+"]卖出票,还有的数量:"+(k--));
    try {
    Thread.currentThread().sleep(500);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    private int k = 10;
    }上面的代码竟然没变色。其实就是加了个Thread.currentThread().sleep(500);再发一次。