真诚的希望大家动手试验下: (new Thread(one)).start(); (new Thread(one)).start(); 这段代码生成了两个引用( reference );但指向同一内存区间,也就是说它们拥有同一个x和同一个y, 因此不会出现 x=1,y=1;x=1,y=1;x=2,y=2;x=2,y=2;这样的现象;而这段代码: x++; //难道在这时候不会转换线程? y++; System.out.println("x=" + x +" , y=" + y); 在注释处完全可以出现“线程转换”,所以x 和 y不相等的时候肯定会出现 稍微修改了一下: /** * @author metaphy */ public class MutiThread implements Runnable { private long x ; private long y ; private int num = 0 ; public static void main(String args[]) { MutiThread one = new MutiThread(); (new Thread(one)).start(); (new Thread(one)).start(); }
public void run() { for(;;) { x++; y++; if (x!= y && num <20){ num ++ ; System.out.println("x=" + x +" , y=" + y); } } } }
答案可能不正确! 在多线程环境中安全问题是最为重要的,不能安全控制并发控制的应用程序在大部分时候能够正常工作(也许几乎所有时间均能正常工作),但有时会发生错误的结果。 我做了一下证明,不对请指出!证明过程我分为两步: 1,证明对一个结果可能显示两次。 2,证明每次显示x和y的值可能不一致。证明如下:当一个方法同时在两个或更多线程中被访问时,每个线程都会有自己的局部拷贝。只有用volatile修饰的变量,VM才不会不会为它分配局部拷贝,才会直接使用共享拷贝。但是在synchronized的同步块之后,系统会自动保持共享拷贝和私有拷贝的一致。更重要的一点是synchronized分布在系统的很多类之中,例如java.*中。System.out.println()就包含一个synchronized。系统认为该保持一致时,也会调整!下面一段程序演示系统是如何更新的(注意我们运行的环境是单处理器): public class MultiThread { private int x; private int y;
public void oper(int sleeptime){ x++; try{Thread.sleep(sleeptime);}catch(Exception e){} y++; }
下面是我运行的结果。(我把for循环改成了从0到9)x=2 , y=1
x=3 , y=2
x=4 , y=3
x=5 , y=4
x=6 , y=5
x=7 , y=6
x=8 , y=7
x=9 , y=8
x=10 , y=9
x=11 , y=10
x=12 , y=11
x=13 , y=12
x=14 , y=13
x=15 , y=14
x=16 , y=15
x=17 , y=16
x=18 , y=17
x=19 , y=18
x=19 , y=19
x=20 , y=20
你看清楚,这儿用synchronized了么?
你没看我给出的运行结果???
{
for(;x<50;)
{
x++;
try
{
Thread.sleep(50);//按理说,即使我不强迫它,
//另外一个线程也有机会抢占啊?可是不强迫时结果却是D,奇怪??
}
catchInterruptedException e)
{
}
y++;
System.out.println("x=" + x +" , y=" + y);
}
}看看结果:x=2 , y=1
x=2 , y=2
x=4 , y=3
x=5 , y=4
x=6 , y=5
x=7 , y=6
x=8 , y=7
x=9 , y=8
x=10 , y=9
x=11 , y=10
x=12 , y=11
x=13 , y=12
x=14 , y=13
x=15 , y=14
x=16 , y=15
x=17 , y=16
x=18 , y=17
x=19 , y=18
x=20 , y=19
x=21 , y=20
x=22 , y=21
x=22 , y=22
x=24 , y=23
x=25 , y=24
x=26 , y=25
x=27 , y=26
x=28 , y=27
x=29 , y=28
x=30 , y=29
x=31 , y=30
x=32 , y=31
x=33 , y=32
x=34 , y=33
x=34 , y=34
x=36 , y=35
x=37 , y=36
x=38 , y=37
x=39 , y=38
x=40 , y=39
x=41 , y=40
x=42 , y=41
x=43 , y=42
x=44 , y=43
x=45 , y=44
x=46 , y=45
x=47 , y=46
x=48 , y=47
x=49 , y=48
x=50 , y=49
x=50 , y=50
Press any key to continue...
这么简单的问题都不知道。
cpu处理多线程是靠分时操作来实现的。
这里虽然起了两个线程,但是前一个线程在不断循环的过程中,后一个线程根本得不到执行
而等待第一个线程执行完后,后一个线程已经不满足运行的条件了。
所以是事实上只是单线程工作。
而它也必须等到其它的线程释放后才能继续执行
所以在x++后加了Thread.sleep,该线程的y++没得到执行,所以x,y出现不等现象
你回答了3句话就只有一句话对。
cpu处理多线程是靠分时操作来实现的。
//就这句是对的。这里虽然起了两个线程,但是前一个线程在不断循环的过程中,后一个线程根本得不到执行
而等待第一个线程执行完后,后一个线程已经不满足运行的条件了。
//你自己也说多线程是靠分时操作来实现的。那么前一个线程运行段时间后必然要中断,把时间片让给后一个线程,所以后一个线程怎么会得不到执行。
//还有“第一个线程执行完后”,这是你的原话,第一个线程是永远不可能执行完的,你没看程序吗?for是个死循环。所以是事实上只是单线程工作。
//综合前面2个问题,你第3句话更是错上加错。对你的忠告不要瞧不起考证,至少我们考过证的比你基础好。
如果要测试的话,你会苯到不设循环条件?
前一线程如果不做你们所谓的延时(Thread.sleep),而且是死循环的话,
后一线程将永得不到执行,而你电脑也处于死循环中,不能做其它的事情
我工作已有4年,多线程写的多了。
我敢说你根本没有实际应用过多线程,除非你是抄别人的//实在不知道你是怎么得出的结论 flyforlove(为情飞) 拜托你好好看书,自己动手做做!
以下是我用搂住的程序运行的结果:
………………
x=5168 , y=5168
x=5169 , y=5169
x=5170 , y=5170
x=5171 , y=5172
x=5171 , y=5172
x=5172 , y=5173
x=5173 , y=5174
x=5174 , y=5175
x=5175 , y=5176
………………
算到5000多的时候,x和y就开始不一样了,也就是说,答案B才是正确的。
说明:我测试使用的程序中间没有用任何延时。
2. 在run()函数的for循环之前加上一条 threadID ++;
3. 每个循环中,在输出x、y之前输出threadID的值;
4. 编译并运行程序,得到的结果是
threadID = 2, x = ……, y = ……显然,只有第二个线程运行过,threadID才可能是2。
既然第二个线程能够运行,x和y的值就很难永远保持一致。所以,答案应该是 B。
(new Thread(one)).start();你要看清楚这里是同一个对象生成的线程,
《JAVA专题技术综述之线程篇》
这本电子书里面说得很清楚,建议你看看
synchronized public void run()//^_^
{
while(true)
{
x++;y++;
if(x!=y){
System.out.println("x=" + x +" , y=" + y);
}
}
}
}
你们不是加了for循环的条件了么?
如果要测试的话,你会苯到不设循环条件?
前一线程如果不做你们所谓的延时(Thread.sleep),而且是死循环的话,//这种话你也敢讲
后一线程将永得不到执行,而你电脑也处于死循环中,不能做其它的事情
我工作已有4年,多线程写的多了。 //你工作这么久了还不知道这种基础知识,真是佩服你
--------------------------------------------------------------------------
你把打印语句改成 System.out.println(Thread.currentThread().getName()+" x=" + x +" , y=" + y);
你自己看看后一个线程运行了吗?劝你不要乱嚷嚷,用事实说话。
内容 谁能保证自己没有错误?
你算什么东西!?
-------------------------------------------------------------------
帮你指出错误,还用短消息骂人,你这种人都有......
内容 你他妈真是呕心
---------------------------------
社会的毒瘤,就你还是程序员,还什么“我工作已有4年,多线程写的多了”,还比不上初学者。只会骂人,有本事把问题说清楚。
他骂人你可以跟斑竹讲,扣他的信誉分
for(int a=0;a<100;a++){
System.out.println("aaa");
}
运行一下就知道了。
Thread-0 x=1 , y=1
Thread-0 x=2 , y=2
Thread-0 x=3 , y=3
Thread-0 x=4 , y=4
Thread-0 x=5 , y=5
Thread-0 x=6 , y=6
Thread-0 x=7 , y=7
Thread-0 x=8 , y=8
Thread-1 x=9 , y=9
Thread-1 x=10 , y=10
Thread-1 x=11 , y=11
Thread-1 x=12 , y=12
Thread-1 x=13 , y=13
Thread-1 x=14 , y=14
Thread-1 x=15 , y=15
Thread-1 x=16 , y=16
Thread-1 x=17 , y=17
Thread-1 x=18 , y=18
Thread-1 x=19 , y=19
Thread-1 x=20 , y=20
Thread-1 x=21 , y=21
Thread-1 x=22 , y=22
Thread-1 x=23 , y=23
Thread-1 x=24 , y=24
Thread-1 x=25 , y=25
Thread-1 x=26 , y=26
Thread-1 x=27 , y=27
Thread-1 x=28 , y=28
Thread-1 x=29 , y=29
Thread-1 x=30 , y=30
Thread-1 x=31 , y=31
Thread-1 x=32 , y=32
Thread-1 x=33 , y=33
Thread-1 x=34 , y=34
Thread-0 x=35 , y=35
Thread-0 x=36 , y=36
Thread-0 x=37 , y=37
Thread-0 x=38 , y=38
Thread-0 x=39 , y=39
Thread-0 x=40 , y=40
Thread-0 x=41 , y=41
Thread-0 x=42 , y=42
Thread-0 x=43 , y=43
Thread-0 x=44 , y=44
Thread-0 x=45 , y=45
Thread-0 x=46 , y=46
Thread-0 x=47 , y=47
Thread-0 x=48 , y=48
Thread-0 x=49 , y=49
Thread-0 x=50 , y=50
Thread-0 x=51 , y=51
Thread-0 x=52 , y=52
Thread-0 x=53 , y=53
Thread-0 x=54 , y=54
Thread-0 x=55 , y=55
Thread-0 x=56 , y=56
Thread-0 x=57 , y=57
Thread-0 x=58 , y=58
Thread-0 x=59 , y=59
Thread-0 x=60 , y=60
Thread-1 x=61 , y=61
Thread-1 x=62 , y=62
Thread-1 x=63 , y=63
Thread-1 x=64 , y=64
Thread-1 x=65 , y=65
Thread-1 x=66 , y=66
Thread-1 x=67 , y=67
Thread-1 x=68 , y=68
Thread-1 x=69 , y=69
Thread-1 x=70 , y=70
Thread-1 x=71 , y=71
Thread-1 x=72 , y=72
Thread-1 x=73 , y=73
Thread-1 x=74 , y=74
Thread-1 x=75 , y=75
Thread-1 x=76 , y=76
Thread-1 x=77 , y=77
Thread-1 x=78 , y=78
Thread-1 x=79 , y=79
Thread-1 x=80 , y=80
Thread-1 x=81 , y=81
Thread-1 x=82 , y=82
Thread-1 x=83 , y=83
Thread-1 x=84 , y=84
Thread-0 x=85 , y=85
Thread-0 x=86 , y=86
Thread-0 x=87 , y=87
Thread-0 x=88 , y=88
Thread-0 x=89 , y=89
Thread-0 x=90 , y=90
Thread-0 x=91 , y=91
Thread-0 x=92 , y=92
Thread-0 x=93 , y=93
Thread-0 x=94 , y=94
Thread-0 x=95 , y=95
Thread-0 x=96 , y=96
Thread-0 x=97 , y=97
Thread-0 x=98 , y=98
Thread-0 x=99 , y=99
Thread-0 x=100 , y=100
if (x !=y)
System.out.println(tn + ": x=" + x + " , y=" + y);Thread-0: x=129100250 , y=129100249Thread-0: x=129100251 , y=129100250Thread-0: x=129100252 , y=129100251Thread-0: x=129100253 , y=129100252Thread-0: x=129100254 , y=129100253Thread-0: x=129100255 , y=129100254Thread-0: x=129100256 , y=129100255Thread-0: x=129100257 , y=129100256Thread-0: x=129100258 , y=129100257Thread-0: x=129100259 , y=129100258Thread-0: x=129100260 , y=129100259Thread-0: x=129100261 , y=129100260Thread-0: x=129100262 , y=129100261Thread-0: x=129100263 , y=129100262Thread-1: x=129100263 , y=129100250Thread-0: x=129100264 , y=129100251Thread-1: x=129100265 , y=129100252Thread-0: x=129100266 , y=129100253Thread-1: x=129100267 , y=129100254Thread-0: x=129100268 , y=129100255Thread-1: x=129100269 , y=129100256Thread-0: x=129100270 , y=129100257Thread-1: x=129100271 , y=129100258Thread-1: x=129100272 , y=129100259Thread-1: x=129100273 , y=129100260Thread-1: x=129100274 , y=129100261Thread-1: x=129100275 , y=129100262Thread-1: x=129100276 , y=129100263Thread-0: x=129100277 , y=129100264Thread-0: x=129100278 , y=129100265很明显,选B
答案肯定是d。你们都是试验过了。shihuash11(ssh) 说得没错,
这段程序中run函数的无限循环没有主动放弃线程的语句,比如sleep,所以当前线程肯定不会放弃执行的。不过windows操作系统的调度方式会保证每个线程都有机会执行的。所以你们的结果也不奇怪。你去Solaris下用绿色线程试试看。保证不会出现线程切换的情况!
x=22473 , y=22473
x=22474 , y=22474
x=22475 , y=22475
x=22476 , y=22476
x=22477 , y=22477
x=22478 , y=22478
x=22479 , y=22479
x=22480 , y=22480
x=22481 , y=22481
x=22467 , y=22482
x=22468 , y=22483
x=22469 , y=22484
x=22470 , y=22485
x=22471 , y=22486
x=22472 , y=22487x突然就小了,哈哈
这是我的一点愚见:
我第一次看,我觉得选择D是有道理的。
因为java 多线程设计时,优先级相同时, 不会主动让出cpu的.
但是,这与OS 相关,有的用分时轮转,有的用优先级调度,多级轮转,有的多者兼备.
还有实时操作系统.
所以,线程在 java 虚拟机种虽然没有可能去主动让cpu.
但是,OS如win ,肯定会让多个线程得到执行,即便是优先级高的,也不能始终占有时间片.所以我倾项B.在实际windows下也确实是B
其中也有一道类似的题(凭记忆是一样的),除了在 for(;;) 语句前有一个 synchronized 修饰。所以我选择了 D,不知道对错。
(new Thread(one)).start();
这段代码生成了两个引用( reference );但指向同一内存区间,也就是说它们拥有同一个x和同一个y, 因此不会出现 x=1,y=1;x=1,y=1;x=2,y=2;x=2,y=2;这样的现象;而这段代码:
x++;
//难道在这时候不会转换线程?
y++;
System.out.println("x=" + x +" , y=" + y);
在注释处完全可以出现“线程转换”,所以x 和 y不相等的时候肯定会出现
稍微修改了一下:
/**
* @author metaphy
*/
public class MutiThread implements Runnable
{
private long x ;
private long y ;
private int num = 0 ;
public static void main(String args[])
{
MutiThread one = new MutiThread();
(new Thread(one)).start();
(new Thread(one)).start();
}
public void run()
{
for(;;)
{
x++;
y++;
if (x!= y && num <20){
num ++ ;
System.out.println("x=" + x +" , y=" + y);
}
}
}
}
在多线程环境中安全问题是最为重要的,不能安全控制并发控制的应用程序在大部分时候能够正常工作(也许几乎所有时间均能正常工作),但有时会发生错误的结果。
我做了一下证明,不对请指出!证明过程我分为两步:
1,证明对一个结果可能显示两次。
2,证明每次显示x和y的值可能不一致。证明如下:当一个方法同时在两个或更多线程中被访问时,每个线程都会有自己的局部拷贝。只有用volatile修饰的变量,VM才不会不会为它分配局部拷贝,才会直接使用共享拷贝。但是在synchronized的同步块之后,系统会自动保持共享拷贝和私有拷贝的一致。更重要的一点是synchronized分布在系统的很多类之中,例如java.*中。System.out.println()就包含一个synchronized。系统认为该保持一致时,也会调整!下面一段程序演示系统是如何更新的(注意我们运行的环境是单处理器):
public class MultiThread
{
private int x;
private int y;
public void oper(int sleeptime){
x++;
try{Thread.sleep(sleeptime);}catch(Exception e){}
y++;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public static void main(String args[])
{
final MultiThread one = new MultiThread();
Runnable r1=new Runnable(){
public void run(){
for(int i=0;i<3;i++)
{
one.oper(1000);
System.out.println("x="+one.getX()+"y="+one.getY()+" "+
Thread.currentThread().getName());
}
}
};
Thread t1=new Thread(r1);
t1.start();
Runnable r2=new Runnable(){
public void run(){
for(int i=0;i<3;i++)
{
one.oper(2000);
System.out.println("x="+one.getX()+"y="+one.getY()+" "+
Thread.currentThread().getName());
}
}
};
Thread t2=new Thread(r2);
t2.start();
}
} //运行结果如下:
x=2y=1 Thread-0
x=3y=2 Thread-0
x=4y=3 Thread-1
x=5y=4 Thread-0
x=5y=5 Thread-1
x=6y=6 Thread-1
Press any key to continue...从结果可以很清楚的看出系统是怎样更新私有拷贝与共享拷贝的(与楼主问题略有不同,sleep是同步的)。
Thread-0首先运行,在执行x++后休眠,此时变量为 x=1,y=0;
Thread-1运行,在执行x++后休眠,此时变量为 x=2,y=0;
Thread-0运行,执行y++,打印结果, x=2,y=1
Thread-0运行,执行x++后休眠,变量为 x=3,y=1
Thread-1运行,执行y++,打印结果, x=3,y=2
.......
我们会发现,system.out.println是在执行了x++和y++之后执行的。换句话说,x,y的值是在执行system.out.println之前是线程的私有拷贝,它的变化不会影响其它线程。只有在执行了system.out.println之后才会使共享拷贝和私有拷贝保持一致。我们可以假设某时刻x与y的值保持一致(设x=X1,y=Y1),这点很显然,至少启动时是。证(1)thread-i在x++之前中断或之后中断,Thread-i的局部拷贝是x=X1,y=Y1或x=X1+1,y=Y1+1,thread-j开始执行,初始值x=X1,y=Y1,执行若干次后为X1+n,Y1+n,再执行system.out.println显示结果,使thread-i中的局部变量调整为x=X1+n,y=Y1+n,thread-i执行system.out.println显示结果x=X1+n,y=Y1+n,既一个结果出现两次!
证(2)Thread-i在x++后中断,Thread-i的局部拷贝是x=X1+1,y=Y1,thread-j开始执行,初始值x=X1,y=Y1,执行若干次后为X1+n,Y1+n,再执行system.out.println显示结果,使thread-i中的局部变量调整为x=X1+n,y=Y1+n,thread-i执行y++,使x=X1+n,y=Y1+n+1,再执行system.out.println,thread-j中局部变量调整为x=X1+n,y=Y1+n+1。 不一致!问题证毕!所结果就和系统调度有关!这么多人都有不同的结果,相信也是有道理的!实际编程这种问题肯定是要排除的!不晓得出这种题干什么!一小段结果:
x=11408980 , y=11408983
x=11408981 , y=11408984
x=11408982 , y=11408985
x=11408983 , y=11408986
x=11408984 , y=11408987
x=11408985 , y=11408988
x=11408986 , y=11408989
x=11408987 , y=11408990
x=11408988 , y=11408991
x=11408989 , y=11408992
x=11408990 , y=11408993
x=11408991 , y=11408994
x=11408992 , y=11408995
x=11408993 , y=11408996
x=11408994 , y=11408997
x=11408995 , y=11408998
x=11408996 , y=11408999
x=11408997 , y=11409000
x=11408998 , y=11409001
x=11408999 , y=11409002
x=11409000 , y=11409003
x=11409001 , y=11409004
x=11409002 , y=11409005
x=11409003 , y=11409006