菜鸟的多线程问题 for(int k = 10 ;k>0;){}简单来说,线程t1,执行10次 k=10,k=9,k=8...线程t2,执行10次 k=10,k=9,k=8...楼主加断点DEBUG下,自己看比较清楚 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你这样肯定有问题啊,每个线程都执行一个单独的实例。 就是说你线程一里面的k和你线程二里面的k根本就不是一个。你要把k放到一个公共区里面,而且还要加锁 你这个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 的线程 。 因为k在for循环中时,是局部变量,并不是两个线程共享的,而是独立的。而第一情况k是实例变量,两个线程的Runnable实例对象相同,访问的是同一个实例变量k。 能出现第一种情况真是侥幸k为成员变量时会出现资源竞争的问题,此时需要对共享资源进行同步(synchronized or lock)建议看一下线程状态和CPU调度相关资料 哦,看错了。用的一个对象,你把k改成1000再试一下呢也就是说,那个k变了?可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?这就是我问题的根本想问的! 1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍? 1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?每个线程都有自己的栈,用来存储线程中的本地变量,也就是变量k,t1和t2分别拥有自己的栈信息,分别保存了本地变量k的副本,互不影响,所以各打印10次 1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符 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拿到相同的值呢? 哦,看错了。用的一个对象,你把k改成1000再试一下呢也就是说,那个k变了?可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?这就是我问题的根本想问的!两个线程引用的同一个任务对象 mr,所以k中共用的。然后你run方法肯定是每个线程都有一个自己的run方法,你可以在run里面定义一个自加变量测一下,看一下每个线程是不是的变量是不是独立的。 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 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,看是否还可打印相同的值 如你所说,的话,好像是这样,但是不是。首先, --k也能有相同的数字。其次,我代码大概是public void run(){ for(;k>0;) system.out.println(........ --k);}int k = 10 ; 如你所说,的话,好像是这样,但是不是。首先, --k也能有相同的数字。其次,我代码大概是public void run(){ for(;k>0;) system.out.println(........ --k);}int k = 10 ;错了,我忘了 -- ++操作不是原子操作,可能会出现重复值,sorry,假设这里用java的原子操作,那么就不会出现相同的值。我说的意思就是,CPU会给每个就绪的线程分配时间片,如果一个线程的时间片到期,就会轮到其他线程执行,如果在线程切换的时候刚好改变了某些资源的状态,就会出现数据不一致的情况,这个时候就需要对资源进行同步,保证数据的一致性。 表示你第一种写法得出的结果简直是侥幸。第一种写法没错,只不过运行结果让你迷惑了。试试下面的写法,让当前线程先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;} 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);再发一次。 求一生成阵列的简便代码 SWT中如何能够重新加载控件? 这个action跳转到那个页面或者程序里去了 面试了两次,都是考基础题,我没有把基础题复习好,我真是失败。明天我又到一家公家面试,求祝福......... 请问为什么我的输出的GUI没有按钮和对话框? 新手求教java文件读取 关于数据类型转换问题 j2me的TimerTask跟线程有什么区别吗? 改FileChooser急求 大家看我这简单的程序那里错了?为什么没有我想要的结果? 请帮我看看这个通配符泛型错在哪里? 为什么这个泛型不成功?
你要把k放到一个公共区里面,而且还要加锁
public void run() {
for(;k>0;){
System.out.println("当前线程["+Thread.currentThread().getName()+"]卖出票,还有的数量:"+(k--));
if( k == 0 )
System.out.println("当前线程["+Thread.currentThread().getName()+"]没票了");
}
}都是线程-2工作,被卖的数量没错!----> 这个你多运行几次会发现有1 的线程 。
可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?
这就是我问题的根本想问的!
1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?
1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?每个线程都有自己的栈,用来存储线程中的本地变量,也就是变量k,t1和t2分别拥有自己的栈信息,
分别保存了本地变量k的副本,互不影响,所以各打印10次
1、k成为成员变量时会出现资源竞争?书上没写,能否解释下?
2、我的k成为for的临时变量时,到是没竞争了,可是咋多运行了一倍!我个人觉得,两个线程引用一个Runnable中的run(),那么怎么会引用出2倍?第一个问题
当k是成员变量时,t1 t2指向一块内存,也就是变量k,而不是在各自的栈中保存k的副本,
此时就是对变量k的竞争,如果当t1改变了k的值,此时,t1挂起,CPU调度t2执行,则t2得到的是被t1改变了的k的值,这就与预期想得到的值不符
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拿到相同的值呢?
可是,t1和t2是引用同一个Runnable中的run方法啊?那么他们引用的run()里面的内容也该相同吧?
这就是我问题的根本想问的!
两个线程引用的同一个任务对象 mr,所以k中共用的。然后你run方法肯定是每个线程都有一个自己的run方法,你可以在run里面定义一个自加变量测一下,看一下每个线程是不是的变量是不是独立的。
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
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,看是否还可打印相同的值
如你所说,的话,好像是这样,但是不是。
首先, --k也能有相同的数字。
其次,我代码大概是public void run(){
for(;k>0;)
system.out.println(........ --k);
}
int k = 10 ;
如你所说,的话,好像是这样,但是不是。
首先, --k也能有相同的数字。
其次,我代码大概是public void run(){
for(;k>0;)
system.out.println(........ --k);
}
int k = 10 ;错了,我忘了 -- ++操作不是原子操作,可能会出现重复值,sorry,假设这里用java的原子操作,那么就不会出现相同的值。
我说的意思就是,CPU会给每个就绪的线程分配时间片,如果一个线程的时间片到期,就会轮到其他线程执行,如果在线程切换的时候刚好改变了某些资源的状态,就会出现数据不一致的情况,这个时候就需要对资源进行同步,保证数据的一致性。
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;
}
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);再发一次。