【问题标题】:Suspend Resume Threads: Java暂停恢复线程:Java
【发布时间】:2015-02-21 09:50:40
【问题描述】:

当我运行这段代码时,它会显示以下输出:

One : 15 Two : 15 One : 14 Two : 14 Two : 13 One : 13 Two : 12 One : 12 One : 11 Two : 11 Thread 1 suspended Two : 10 Two : 9 Two : 8 Two : 7 Two : 6 Thread 1 resumed Thread 2 suspended Thread 2 resumed

输出不会持续到最后 一:1 二:1 NewThread1类的myresume方法没有执行吗?这背后的原因是什么?

下面是NewThread1的代码:

class NewThread1 implements Runnable{
String name;
Thread t;
boolean suspendFlag;

NewThread1(String threadname){
    name = threadname;
    t = new Thread(this, name);
    suspendFlag = false;
    t.start();
}

@Override
public void run(){
    try{ 
         for(int i=15; i>0; i--){
             System.out.println(name+ " : " +i);
             Thread.sleep(200);
                synchronized(this){
                    while(suspendFlag){
                        wait();
                    }
                }
        }
    }catch(InterruptedException e){
        System.out.println("New thread1 Interrupted");
    }
}
synchronized void myresume(){
    suspendFlag = false;
}
void mysuspend(){
    suspendFlag = true;
}
}        

下面是NewThread1的代码:(这里定义了main()方法)

public class Suspend_ResumeThreads {
public static void main(String args[]){
    NewThread1 ob1 = new NewThread1("One ");
    NewThread1 ob2 = new NewThread1("Two ");

    try{
        Thread.sleep(1000);
        ob1.mysuspend();
        System.out.println("Thread 1 suspended");
        Thread.sleep(1000);
        ob1.myresume();
        System.out.println("Thread 1 resumed");

        ob2.mysuspend();
        System.out.println("Thread 2 suspended");
        Thread.sleep(1000);
        ob2.myresume();
        System.out.println("Thread 2 resumed");

    }catch(InterruptedException e){
        System.out.println("Main Interrupted");
    }

    try{
        ob1.t.join();
        ob2.t.join();
    }catch(InterruptedException e){
        System.out.println("Main interrupeted in join()");
    }
System.out.println("Main exiting..");    
}
}

【问题讨论】:

  • 您必须在同一个对象上调用.notify() 才能唤醒卡在该对象的.wait() 中的线程。
  • 当您使用通知/等待时,这应该始终与状态更改相关联。 Notify() 可以在没有任何等待的情况下发生,这将丢失,并且 wait() 可以虚假唤醒。
  • 还将suspendFlag 标记为易失性。或在synchronized 部分更改它

标签: java multithreading resume suspend thread-synchronization


【解决方案1】:

使用notifyAll打断wait():放

this.notifyAll();

进入您的myresume() 函数。但请始终准备好让此通知丢失;特别是当当前没有线程在等待时,它仍然会成功。

确保您synchronize/wait/notify相同对象上。一个常见的错误是在this 上进行同步,而没有意识到在匿名内部类的上下文中,this 可能有所不同。更糟糕的是,在重构代码时它可能会发生变化!最佳做法是在某处使用 Object lock = new Object(); 并始终使用 synchronize(lock) ... lock.wait(); ... lock.notifyAll(); 以避免此类编程(和重构)错误。

除非你创建suspendFlagvolatile,否则不同的线程也有可能看到这个字段的不同值(如果不是volatile,线程可能会在CPU缓存中保留一个本地副本)。因此,将mysuspend 同步也可能会很好。

在某些情况下,您可能需要切换到更高级的同步,例如 java.util.concurrent.locks.Lockjava.util.concurrent.Semaphore

【讨论】:

    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 2012-08-08
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多