package countbirds;
public class Machine14 implements Runnable{
private int a=1;
public void run(){
for(int i=0;i<1000;i++){
a+=i;
Thread.yield();
a-=i;
System.out.println(a);
}
}
public static void main(String[] args) throws InterruptedException{
Machine14 machine=new Machine14();
Thread t1=new Thread(machine);
Thread t2=new Thread(machine); t1.start();
t2.start();
}
}为什么这个程序运行的结果是
1
1
1
1
1
...而不是
1
2
2
3
3
...
我不明白我错在哪了,恳请各位赐教
public class Machine14 implements Runnable{
private int a=1;
public void run(){
for(int i=0;i<1000;i++){
a+=i;
Thread.yield();
a-=i;
System.out.println(a);
}
}
public static void main(String[] args) throws InterruptedException{
Machine14 machine=new Machine14();
Thread t1=new Thread(machine);
Thread t2=new Thread(machine); t1.start();
t2.start();
}
}为什么这个程序运行的结果是
1
1
1
1
1
...而不是
1
2
2
3
3
...
我不明白我错在哪了,恳请各位赐教
解决方案 »
- java新手来提问
- 关闭小程序窗口。
- 应届毕业生去日本做j2ee好不好??
- jasperreport的分组报表问题!请高手解答,谢谢!
- 笔试的问题:Unicode与中文的相互转换
- 请帮我看下这个列子,点击按钮开新窗口
- 怎么从远程SQLServer数据库中把数据插入本地数据库JAVA实现????
- JNICALL是不是JAVA里面的东西?那JNICALL是什么类型?
- 王森的Kjava一书中Database类在哪个jdk中??急
- Swing,a方法调用b方法,b方法调用c方法
- 用C/S模式做的JAVA QQ,S端导出JAR包后连不上数据库,连不上1433端口,请高手们支下招吧。。。
- 如何把int数组里的图片显示出来
a+=i;
a-=i; LZ你觉得这两句话是做了什么操作?
而你的代码里面又有
Thread.yield();
让线程休眠的语句,所以出现了1楼的结果
没什么不对的啊还有,你这个问题跟同步没有关系啊
你又没有写同步块
/**
* Causes the currently executing thread object to temporarily pause
* and allow other threads to execute.
*/
public static native void yield();
yield()暂停当前线程,允许起他线程执行。一般来说cpu进行了线程切换,因为系统中不可能只有一个线程。到底切换到什么线程?不知道,整个系统中运行了很多线程(上百个),未必能切换到java程序中的某一个线程去。因为到底切换到哪一个线程无法确定,所以输出什么结果都有可能。注意一点,整个电脑中运行的不只你在jvm里开的2个线程,jvm外还有成百上千的线程在等这cpu。jvm线程暂停,马上切换到另一个jvm线程执行的几率,也就1/100,1/1000.从其他系统线程切换到jvm执行的线程的时候,是不能保证切换到1,还是2的。这个实例说明,多线程一定要同步。
在我机器上的执行结果和楼主预期的差不多
lz机器上的结果可能是
主线程执行
t1.start();
后
转去执行
t1线程
还没有执行t2.start()线程执行时调度的顺序本来就是不可预知的
你这么写不是自己找死吗
public static void main(String[] args) {
TestThread[] runners = new TestThread[2];
for (int i = 0; i < 2; i++) runners[i] = new TestThread(i);
runners[0].setPriority(2); //设置第一个线程优先级为2
runners[1].setPriority(3); //设置第二个线程优先级为3
for (int i = 0; i < 2; i++) runners[i].start();
}
}
class TestThread extends Thread{
private int tick = 1;
private int num;
public TestThread(int i) { this.num=i; }
public void run() {
while (tick < 400000) {
tick++;
if ((tick % 50000) == 0) { //每隔5000进行显示
System.out.println("Thread #" + num + ", tick = " + tick);
yield(); //放弃执行权
}
}
}
}
运行结果
Thread #1, tick = 50000
Thread #1, tick = 100000
Thread #1, tick = 150000
Thread #1, tick = 200000
Thread #1, tick = 250000
Thread #1, tick = 300000
Thread #1, tick = 350000
Thread #1, tick = 400000
Thread #0, tick = 50000
Thread #0, tick = 100000
Thread #0, tick = 150000
Thread #0, tick = 200000
Thread #0, tick = 250000
Thread #0, tick = 300000
Thread #0, tick = 350000
Thread #0, tick = 400000
结果说明
具有较高优先级的线程1一直运行到结束,具有较低优先级的线程0才开始运行
虽然具有较高优先级的线程1调用了yield方法放弃CPU资源,允许线程0进行争夺,但马上又被线程1抢夺了回去,所以有没有yield方法都没什么区别这个例子充分说明了,即使t1线程自己暂停了,放弃cpu资源,但是cpu接下来调度哪个线程是不知道的,有可能调度t2,出现第二种情况,但是也有可能继续调用t1,像上面的例子那样一直抢占,所以出现哪种情况都是很正常的,大家都没有什么错但是在这里我觉得有些人有错:我不明白为什么人家问问题还要被人骂?什么傻B不傻B的,难道回答者很了不起吗?在哪里工作?IBM?微软?在哪里读书?清华北大?恐怕就算这些地方的高级人才也没敢这么骂人,这么骂人是会打击人家的学习信心的,楼主不要放弃,JAVA与你同在。
private boolean otherRun = false;
public void run() {
for (int i = 0; i < 1000; i++) {
a += i;
//Thread.yield();
synchronized (this) {
if (!otherRun) {
otherRun = !otherRun;
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
otherRun = !otherRun;
this.notify();
} finally {
}
}
}
a -= i;
System.out.println(a);
}
}
public static void main(String[] args) {
Machine14 machine = new Machine14(); Thread t1 = new Thread(machine);
Thread t2 = new Thread(machine); System.out.println("Run method");
t1.start();
t2.start();
}}输出结果:
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
..........
Thread.yield这个方法太不可靠,虽然这个方法的目的是让当前线程休息一下,但是谁也不能保证当前线程休息之后接着运行的就一定不是该线程。如果你希望能够同步,还是应该使用wait,notify来控制。