public class Reader extends Thread {
Calculator calc;
public Reader(Calculator calc){
this.calc = calc;
}
public void run(){
synchronized (calc) {
try{
System.out.println(Thread.currentThread().getName()+"Waiting for notify....");
calc.wait();
System.out.println(Thread.currentThread().getName()+"After wait...");
}catch(Exception c){}
}
}
public static void main(String[] args) {
Calculator calculator = new Calculator();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
calculator.start();
}}
class Calculator extends Thread{
int total;
public void run(){
synchronized(this){
for(int i=0;i<3;i++){
total += i;
System.out.println(total);
}
notify();
System.out.println("after notifyAll...");
}
}
}这段代码,notify只通知 了一个。为何所有的wait都执行了??
Calculator calc;
public Reader(Calculator calc){
this.calc = calc;
}
public void run(){
synchronized (calc) {
try{
System.out.println(Thread.currentThread().getName()+"Waiting for notify....");
calc.wait();
System.out.println(Thread.currentThread().getName()+"After wait...");
}catch(Exception c){}
}
}
public static void main(String[] args) {
Calculator calculator = new Calculator();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
calculator.start();
}}
class Calculator extends Thread{
int total;
public void run(){
synchronized(this){
for(int i=0;i<3;i++){
total += i;
System.out.println(total);
}
notify();
System.out.println("after notifyAll...");
}
}
}这段代码,notify只通知 了一个。为何所有的wait都执行了??
Calculator calculator = new Calculator();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
Thread.sleep(1000);
// calculator.start();
synchronized(calculator) {
calculator.notifyAll();
}
}
Calculator calculator = new Calculator();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
Thread.sleep(1000);
// calculator.start();
synchronized(calculator) {
calculator.notify();
}
}
你上面那个程序一切正常,你把你自己加的notify()去掉。然后多运行几次可能会明白,给一个线程类加锁,还启动这个线程类,和给普通类加锁不太一样
线程Reader1-6,和线程Calculator。
当main线程进入到第一句: (new Reader(calculator)).start();
线程Reader1获得锁,开始运行,
这时JVM可能调度Reader2,3,4,5,6线程开始运行,但它们都没有获得锁,所以都block了。
这时,Reader1运行继续运行,然后,显然wait了,JVM可能运行线程Calculator,当执行到notify(),发现只有Reader1在wait,所以只有把它叫醒,Reader1执行完毕,JVM会选择那些还block在该锁上的线程,继续运行。2,notify和notifyAll的区别
JDK文档说的很清楚,关键是何时使用哪个。多数时候,使用notifyAll,这样比较安全。
public class Reader extends Thread {
Calculator calc;
public Reader(Calculator calc){
this.calc = calc;
}
1, public void run(){
2, synchronized (calc) {
3, try{
4, System.out.println(Thread.currentThread().getName()+"Waiting for notify....");
5, calc.wait();
6, System.out.println(Thread.currentThread().getName()+"After wait...");
7, }catch(Exception c){}
8 }
}看上面这个程序,当线程Reader1在执行第5句之前,JVM是有可能把CPU调度给其它线程的,如果这时把CPU调度给Reader2线程,Reader2线程在执行第2句时,需要获得calc变量所指向的锁,由于无法获得,就只能被block(阻挡)了。
百度多少也只是那一句俗语:
notify通知一个。
notifyAll通知全部。
现在活生生的例子放在面前的时候,为什么没人可以合理解释呢。
他这个锁定的是calculator这个对象,而整个程序中,只有一个calculator实例,那么这里不同的Reader访问calculator,会不会出现一些被锁住的情况呢?
按照例子,似乎不会出现这样,那这个怎么解释呢?synchronized锁住的究竟是什么?
可是问题在这里,谁允许那帮wait()自己活过来了??
是JVM这么聪明,说就你们几个还没执行了。赶紧执行吧
你换成 calculator.run() 那铁定你会出现你想要的结果 唤醒其中一个线程
我的意思是 执行这个方法calculator.start()其实就代表了 , 线程激活 , 他是同一个对象执行的wait()
所以全部会唤醒 这里主要就是 在最后执行了calculator.start()这个方法 第一行开始是线程创建 执行此方法就是激活线程 他的wait()状态 就不存在了 大概就是这样 其实具体是不是这样说 我也拿不定 但是确实是这么一回事就是了 楼主不知道是不是做的测试才这么写的代码 按照正常的写法 你做的一些对线程的操作 还是要放在一个类里面的好 Reader 里面再写一个方法去唤醒 这样的问题就可以避免了
Thread-1Waiting for notify....
Thread-2Waiting for notify....
Thread-3Waiting for notify....
Thread-4Waiting for notify....
Thread-5Waiting for notify....
0
1
3
after notifyAll...
notify sleep
Thread-1After wait... //只唤醒了第一个,并且使整个进程处于阻塞状态。
Thread-6Waiting for notify....
我现在想说,那么为什么呢?
start 和 run 区别在哪里?
先申明我不是高手
我给你解释了几次 可能我水平真有问题 没说的你明白 我觉得已经说的差不多了 没必要给你说JDK里面具体是怎么实现的吧 说实话我也不知道就是了
耐心给你解释反倒成了累赘了
最后回答你上面问题一次
start()方法是启动一个线程 里面没错是调用的native方法 具体里面做了什么 我没看过
run()方法 是有java虚拟机调用的
也就是说线程start()没有直接调用run()方法 我上面已经说了 start()是做一个激活线程操作
java虚拟机执行run()方法才是具体的操作内容
还有你问的为什么是这样的这个问题 我想说JDK里面就是这样的 你有办法吗?
前提:
1.在main()后面用了对象calc.start() 或者 calc.run()
2.开始的时候是用同一个对象调用calc.wait();如果你只是显示的调用calc.run() 方法 那他执行calc.notify()一次 就是上面我说的肯定唤醒一个 那就是普遍大家认为的notify唤醒一个线程 notifyAll唤醒全部线程而 calc.start() 启动了线程 把你 同一个对象调用的calc.wait(); 方法 激活了 因为start()方法是要激活这个线程的 你先把他wait()掉了 那么start()方法还怎么启动线程啊 那么jdk肯定是要把wait()状态去掉 才能启动线程啊 我实在是没办法说清楚了 只能说这些了 你还是要问为什么 那我只能撞墙了 别太专牛角尖了
或者说那锁能自己解开吗?
如果不这么做 , 你先wait()了那么start() 难道不让他启动? 他们的思想是要先保证启动一个线程是优先的吧
人家的思想是这样啊
2.或者说那锁能自己解开吗?
你wait()的时候就已经放弃了那把同步锁了 只是让你这个任务对象calc等待执行 挂起
after notifyAll...
Thread-1After wait...
Thread-6After wait...
Thread-5After wait...
Thread-4After wait...
Thread-3After wait...
Thread-2After wait...
我们 去掉 notify()方法,看看。如下class Calculator extends Thread{
int total;
public void run(){
synchronized(this){
for(int i=0;i<3;i++){
total += i;
System.out.println(total);
}
//notify(); 去掉
System.out.println("after notifyAll...");
}
}
}则打印结果如下:after notifyAll...
Thread-6After wait...
Thread-5After wait...
Thread-4After wait...
Thread-3After wait...
Thread-2After wait...
Thread-1After wait...比较两次打印结果变化,楼主写的那个notify()确实只notify了一个(就是thread1), 而其他几个thread到底是被谁,如何被唤醒的,目前本人还不好解释,只能猜测:某个线程结束时,自己调用了一个this.notifyAll(); 这也可以解释前面讨论的调run()和start()的不同表现。
run只是在主线程里运行一个一般的函数
真是说什么的都有啊,你的这个程序逻辑挺简单的啊
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
(new Reader(calculator)).start();
以上线程执行自己的run方法后都进入了calculator对象的等待池。
calculator.start();
执行后,从等待池中随机唤醒一个,之后calculator的run方法结束,并且交出了锁,这个时候重新和唤醒的线程竞争对象锁。