Java Notify()不使用Wait()
我不熟悉线程和学习,但在下面的代码中,为什么notify不起作用。根据我的理解,notify应该执行主线程,并在i=5时打印总数。如果我错了,请改正Java Notify()不使用Wait(),java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我不熟悉线程和学习,但在下面的代码中,为什么notify不起作用。根据我的理解,notify应该执行主线程,并在i=5时打印总数。如果我错了,请改正 public class ThreadA { public static void main(String[] args){ ThreadB b = new ThreadB(); b.start(); synchronized(b){ try{ System.out.println(
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<10 ; i++){
total += i;
if(i==5){
System.out.println("Notify");
notify();
}
System.out.println("Total is in cal thread: "+i+":" + total);
}
}
}
}
当你说:
根据我的理解,notify应该执行主线程,并在i=5时打印总数
这不是怎么回事;无论将调用放在同步块中的什么位置,通知都不会发生,直到通知线程释放锁。ThreadB在主线程收到通知之前完成for循环的执行。接收通知的线程在此之前无法执行任何操作,它需要先获取锁,然后才能离开wait方法。这就是为什么在“总计为”行之前打印出所有“总计为校准”行的原因
如果希望“Total is”提前显示,则必须更改ThreadB以更快地释放其锁。您可以将同步移动到for循环中,以便在每次增量后释放锁
在这里,调用notify实际上是多余的,您可以注释掉它,程序仍然可以工作
这里发生的事情是,因为您使用线程b作为锁,当该线程终止时,等待获取它的任何线程都会收到该线程。以下章节对此进行了描述:
此实现使用This.wait调用的循环,该循环以This.isAlive为条件。当线程终止时,调用this.notifyAll方法。建议应用程序不要在线程实例上使用wait、notify或notifyAll
如果您运行我更改为使用不同锁(不是线程)的这个版本的程序,您可以看到没有此类隐式通知,并且程序调用notify是否真的很重要。在此版本中,注释掉线程b完成的通知将导致程序挂起
public class ThreadA {
public static final Object lock = new Object();
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(lock){
try{
System.out.println("Waiting for b to complete...");
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
System.out.println("done");
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(ThreadA.lock){
for(int i=0; i<10 ; i++){
total += i;
if(i==5){
System.out.println("Notify");
ThreadA.lock.notify(); // hangs if you comment this out
}
System.out.println("Total is in cal thread: "+i+":" + total);
}
}
}
}
公共类ThreadA{
公共静态最终对象锁=新对象();
公共静态void main(字符串[]args){
ThreadB=新的ThreadB();
b、 start();
已同步(锁定){
试一试{
System.out.println(“等待b完成…”);
lock.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“总计为:+b.Total”);
}
系统输出打印项次(“完成”);
}
}
类ThreadB扩展线程{
整数合计;
@凌驾
公开募捐{
已同步(ThreadA.lock){
当你说:
根据我的理解,notify应该执行主线程,并在i=5时打印总数
这不是它的工作方式;在将调用放入notify的同步块中的何处并不重要,通知不会发生,直到通知线程释放锁。ThreadB在主线程收到通知之前完成for循环的执行。接收通知的线程在此之前无论如何都不能动作,它需要s在离开等待方法之前获取锁。这就是为什么所有“总计在校准”行在“总计在校准”行之前打印出来的原因
如果希望“Total is”提前显示,则必须更改ThreadB以更快地释放其锁。可以将同步移动到for循环中,以便在每次增量后释放锁
在这里,调用notify实际上是多余的,您可以注释掉它,程序仍然可以工作
这里发生的事情是,由于您使用线程b作为锁,因此当该线程终止时,等待获取它的任何线程都会接收到该锁
此实现使用以This.isAlive为条件的This.wait调用循环。当线程终止时,将调用This.notifyAll方法。建议应用程序不要在线程实例上使用wait、notify或notifyAll
如果您运行我更改为使用不同锁(不是线程)的这个版本的程序,您可以看到没有此类隐式通知,并且程序调用notify是否真正重要。在这个版本中,注释掉线程b完成的notify将导致程序挂起
public class ThreadA {
public static final Object lock = new Object();
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(lock){
try{
System.out.println("Waiting for b to complete...");
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
System.out.println("done");
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(ThreadA.lock){
for(int i=0; i<10 ; i++){
total += i;
if(i==5){
System.out.println("Notify");
ThreadA.lock.notify(); // hangs if you comment this out
}
System.out.println("Total is in cal thread: "+i+":" + total);
}
}
}
}
公共类ThreadA{
公共静态最终对象锁=新对象();
公共静态void main(字符串[]args){
ThreadB=新的ThreadB();
b、 start();
已同步(锁定){
试一试{
System.out.println(“等待b完成…”);
lock.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(“总计为:+b.Total”);
}
系统输出打印项次(“完成”);
}
}
类ThreadB扩展线程{
整数合计;
@凌驾
公开募捐{
已同步(ThreadA.lock){
对于(int i=0;i
调用notify
只影响当前正在等待的线程,在调用后开始等待的线程将不会受到影响。在同步块内100%确认您等待的事情尚未发生之前,不要调用wait
调用notify
只会影响当前正在等待的线程,在调用后开始等待的线程不会受到影响。在同步块内100%确认您正在等待的事情尚未发生之前,不要调用wait
。如果是多线程,您不确定b.w在调用ThreadB
中的notify()
之前,将调用main
中的ait()
线程。当调用b.start()
时,ThreadB
的run方法将在执行main
线程的其余语句之前开始执行
如果在n之后调用了wait
synchronized(b) {
try{
// b.total needs to be volatile for this to work
while (b.total < 5) {
System.out.println("Waiting for b to complete...");
b.wait();
}
}catch(InterruptedException e){
e.printStackTrace();
}
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
public class ThreadA {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
try {
b.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("Waiting for b to complete...");
System.out.println("Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
total += i;
}
}
}