关于java 两个线程轮换打印1-10的问题

publicclassPrintNumDemo{/***@paramargs*/publicstaticvoidmain(String[]args){PrintNumpn... public class PrintNumDemo {

/**
* @param args
*/
public static void main(String[] args) {
PrintNum pn1=new PrintNum();
PrintNum pn2=new PrintNum();

new Thread(pn1).start();
new Thread(pn2).start();
}

}

public class PrintNum implements Runnable {

public void run() {
PrintN pn=new PrintN();
while(pn.i<101){
synchronized(pn){

System.out.println(Thread.currentThread().getName()+" is printing "+pn.i);

if(pn.i%10==0){
try {
pn.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
pn.i++;
pn.notify();
}
}
}
}

//输出结果

Thread-0 is printing 1
Thread-1 is printing 1
Thread-1 is printing 2
Thread-1 is printing 3
Thread-1 is printing 4
Thread-1 is printing 5
Thread-1 is printing 6
Thread-1 is printing 7
Thread-1 is printing 8
Thread-1 is printing 9
Thread-1 is printing 10
Thread-0 is printing 2
Thread-0 is printing 3
Thread-0 is printing 4
Thread-0 is printing 5
Thread-0 is printing 6
Thread-0 is printing 7
Thread-0 is printing 8
Thread-0 is printing 9
Thread-0 is printing 10

为什么我的线程打印了10就不打印了,为什么线程0和1还可以交替进行,很不解,学艺不精,求高手指教,万分感谢!
展开
 我来答
闲花微凉
2014-03-12 · 超过14用户采纳过TA的回答
知道答主
回答量:29
采纳率:0%
帮助的人:28.6万
展开全部
pn.notify();

notify
public final void notify()

唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。
此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:
通过执行此对象的同步实例方法。
通过执行在此对象上进行同步的 synchronized 语句的正文。
对于 Class 类型的对象,可以通过执行该类的同步静态方法。
一次只能有一个线程拥有对象的监视器。

//我的理解是notify()不能唤醒本身
追问
请问如果修改我的代码 需要如何修改啊?
追答
其实我也不太懂。。。。我寒假自己看了会儿书。。。。要是我的话一定傻傻的sleep
public class PrintNumDemo {

/**
* @param args
*/
public static void main(String[] args) {
PrintNum pn1=new PrintNum();
PrintNum pn2=new PrintNum();

new Thread(pn1).start();
new Thread(pn2).start();
}

}

public class PrintNum implements Runnable {

public void run() {
PrintN pn=new PrintN();
while(pn.i<101){
synchronized(pn){

System.out.println(Thread.currentThread().getName()+" is printing "+pn.i);

if(pn.i%10==0){
try {
pn.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
pn.i++;
}
}
}
}
woaihouzhuang
2014-03-12 · TA获得超过259个赞
知道小有建树答主
回答量:245
采纳率:100%
帮助的人:228万
展开全部
先回答问题:
1、为什么打印到10就不打印了?因为打印到10 以后,满足1%10 == 0 ,然后线程wait()了,却没有任何其他的线程唤醒,当然不打印了!没有线程唤醒?是的!下面的pn.notify()是无法唤醒的,因为没有执行的机会。另外一个线程可能会执行这句话,但是那个pn和这个pn不是同一个对象,所以无法唤醒!若要其他线程唤醒此线程,则需要使用同一个对象同一把锁进行同步!
2、0和1交替打印很正常啊,你多执行几次,会发现每次和每次的打印都不一样,都是随机打印。为什么?你的同步使用是错误的。

结论:线程同步可以使用synchronized关键字,而该关键字要求若多个线程之间进行同步,需要使用恰当的对象锁,否则结果不可预料。
追问
谢谢你的回答,如果我想实现交替打印1-10,在我的代码基础上该如何修改,请指教
追答
这里有个详细说明:easynoder.org/note/xe1xvs3hfv
本回答被提问者和网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
sadqesadqe
2014-03-12 · 超过13用户采纳过TA的回答
知道答主
回答量:29
采纳率:0%
帮助的人:22.4万
展开全部
我没有实际测试,有可能是如下原因
你的两个线程各自拿自己的线程锁,而不是同一个线程锁,因此最后都处于wait,你可以在main函数中定义一个公共线程锁(一个对象)如 public static Object ob = new Object();
两个线程都用此锁synchronized(ob),应该可以互相唤醒,你试试吧
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
lichenbill
2014-03-12 · 超过13用户采纳过TA的回答
知道答主
回答量:34
采纳率:0%
帮助的人:31.6万
展开全部
你的代码最后的结果就是这样的。因为pn对于每个PrintNum对象你都是重新new 了一个,就是说pn1的pn和pn2的pn不是同一个对象,于是上锁的时候都各自管各自的锁。如果要达到你的效果必须把PrintN pn(虽然我不知道是什么东西)设置成静态的全局变量。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式