关于Object.wait(long t)的问题,请指教

SmileAndHappy 2005-04-13 05:48:40
下面的代码照理应该输出1000左右的数字,但是输出的是64.
我是这样想的:
首先Object.wait(long t)是很精确的,Timer类也是用该
方法来实现执行时间的安排的。
然后看run函数,在stop前做一个无限循环,而且获得本身
的管程,所以每次执行wait(1)这条语句都会停留1微秒,
然后作cnt的加操作,所以经过1000毫秒的sleep应该加到
1000才对呀,请问大家我想的错在哪里?

public class Test implements Runnable {
boolean flag = true;
int cnt = 0;
public void run() {
System.out.println("start");
synchronized(this) {
while(flag) {
try {
wait(1);
cnt++;
}catch(Exception e){}
}
}
}

void stop() {
flag = false;
System.out.println("cnt="+cnt);
}

public static void main(String[] args) throws Exception {
Test t = new Test();
Thread thread = new Thread(t);
thread.start();
Thread.sleep(1000);
t.stop();
}
}
...全文
294 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingfish 2005-04-13
  • 打赏
  • 举报
回复
Object o = new Object();
long start = 0;
start = System.currentTimeMillis();
synchronized (o) {
for (int i = 0; i < 1000; ++i) {
o.wait(1);
}
}
System.out.println(System.currentTimeMillis() - start);

以我本机为例:
大概耗时 1090ms, 所以wait(1)的时间大概1.09ms
那么1000/1.09=917
和我运行第一个程序的值非常接近.
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
我还没完全看懂Timer 的代码,我发现这个类的代码不多, 多花点时间应该能看懂^_^
kingfish 2005-04-13
  • 打赏
  • 举报
回复
Timer类是做了一个任务队列来pooling的, 队列采用wait/notify,
我想这比wait(1)更准确.
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
不是的,Timer类是完全用java代码实现的,我看过没有用native 方法的。
ysbcg 2005-04-13
  • 打赏
  • 举报
回复
楼上 不要忘了 java系统的底层 是用c实现的
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
import java.util.*;

class Task extends TimerTask {
int a = 0;
public void run() {
a++;
}
public int getCnt() {
return a;
}
}

public class Test {
public static void main(String[] args) throws Exception {
Timer tm = new Timer();
Task tsk = new Task();
tm.scheduleAtFixedRate(tsk, 0, 1);
Thread.sleep(1000);
tm.cancel();
System.out.println(tsk.getCnt());
}
}

用Timer类实现计时就可以输出1001,都是用Object.wait(long t)来实现的,类库实现者就是
强啊。而且Timer sched函数代码比我的多很多,附加的时间因该更多呀,不知道为什么他们能做
到如此的“实时性”。
ysbcg 2005-04-13
  • 打赏
  • 举报
回复
一。系统中的时钟是不可能十分准确的
呵呵 这个归功于 当时ibm设计pc的时候的计时方式,即时钟中断。这个中断每秒大约产生18次(55ms一次).
DOS以后的操作系统吧他继承下来了。
二。你的程序执行的时候也占用了一定的时间,而且windows系统是一个多线程的抢占式系统。这会使你的程序不会完全占用系统的cpu也就无法准确的计数。
kingfish 2005-04-13
  • 打赏
  • 举报
回复
另外,考虑到线程启动需要时间,需要中其它指令的时间,8xx-9xx比较正常
====
循环
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
果然改为volatile boolean 输出就有500多了
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
楼上的大哥说的有理,一定给分。
“需要中-->改为 循环中”什么意思。
kingfish 2005-04-13
  • 打赏
  • 举报
回复
需要中-->改为 循环中
kingfish 2005-04-13
  • 打赏
  • 举报
回复
我的机器上执行了多次,大概在7xx--9xx

另外,有一点要改
volatile boolean flag = true;
========
这个就不用解释了吧

另外,考虑到线程启动需要时间,需要中其它指令的时间,8xx-9xx比较正常.
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
没人顶只有自己来了。
SmileAndHappy 2005-04-13
  • 打赏
  • 举报
回复
楼上说的不太对吧,启动线程的时间可以忽略的。而且我用的是
wait(1)在一个毫秒内肯定能轮到该线程占用cpu的。
每次运行这个程序都是输出64,不太像是随机的。
ChDw 2005-04-13
  • 打赏
  • 举报
回复
这个可能和实际环境有关
你要注意,在调用start时,JVM启动一个新的线程,但是这个是需要花费时间的,所以到进入run方法已经过了好一会儿了
飞行的兔子 2005-04-13
  • 打赏
  • 举报
回复
程序并不是按照你想的方式运行!
main线程和你产生的线程是轮流共享cpu,它们何时该谁运行并不知道,不可能是你想的那样输出再1000左右!
飞行的兔子 2005-04-13
  • 打赏
  • 举报
回复
Thread.sleep(1000);
按照楼主的想法这句应该改成Thread.currentThread().sleep(1000);

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧