Java线程挂起不起作用

时间:2016-02-23 22:16:05

标签: java multithreading

这是使用java线程的示例代码。问题是我无法暂停该帖子。

public class RunnableDemo implements Runnable {
   public Thread t;
   private String threadName;
   boolean suspended = false;
   RunnableDemo( String name){
       threadName = name;
       System.out.println("Creating " +  threadName );
   }
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         while (true) {
            System.out.println("Thread: " + threadName + ", " + i);
            // Let the thread sleep for a while.
            Thread.sleep(300);
            synchronized(this) {
               while(suspended) {
                  wait();
               }
            }
        }
     } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
     }
     System.out.println("Thread " +  threadName + " exiting.");
   }
   public void start ()
   {
      System.out.println("Starting " +  threadName );
      if (t == null)
      {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
   public void suspend() {
      suspended = true;
   }

下面的暂停功能不起作用:

RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
R1.suspend();  // This line does not work and thread continues ...

实际上,当我调用suspended时,线程看不到suspend()的新值。有什么想法吗?

3 个答案:

答案 0 :(得分:3)

suspended声明为volatile

volatile boolean suspended = false;

答案 1 :(得分:1)

我并不完全清楚你想要达到的目标,但这里有一些观察和提示可能有所帮助:

  • 当主线程完成suspend()方法时,第二个线程" Thread-1"可能甚至没有进入循环。如果在suspend()以及wait()之前和之后添加更多调试输出,您将看到此信息。反之亦然,您可以在wait()设置为true之前调用suspend。然后,一旦调用wait(),您就不会在" Thread-1"中看到更多更新。因为它在等待。
  • wait()方法永远不会返回。要实现此目的,请在调用wait()时同步您同步的同一对象,即在main方法中调用R1并在此对象上调用notifyAll()。您也可以在suspend()方法中执行此操作。
  • 这种方法使Thread.sleep()之类的方法变得非常不必要。呼叫wait()没有主动等待,并且不会消耗大量资源。

简而言之,将暂停方法更改为

void suspend() {
   suspended = true;
   synchronized (this) {
       this.notifyAll();
   }
}

这将改变您的程序行为方式,并使其更加清晰。但无论哪种方式,它似乎都没有"暂停"这个方法在之前或之后的作用是一个很好的名称,但如果你试验这个,你可以更好地理解你如何实现你想要达到的目标。

答案 2 :(得分:1)

使用wait()可能无法按预期工作。 wait / notify构建为并发编程的sempaphore(作为对象实例范围监视器)上下文的简单实现。 从没有锁定线程对象实例的监视器的任何其他线程调用notify()都不起作用,请参阅Java Wait and Notify: IllegalMonitorStateException

您可以通过定期检查暂停标志轻松实现目标,如果您的主题不做任何事情,请稍等一下:

public class SuspendDemo implements Runnable {
    public Thread t;
    private final String threadName;
    boolean suspended = false;
    SuspendDemo(final String name){
        threadName = name;
        System.out.println("Creating " +  threadName );
    }

    @Override
    public void run() {
        System.out.println("Running " +  threadName );
        try {
            while (true) {
                System.out.println("Thread: " + threadName);
                // Let the thread sleep for a while.
                Thread.sleep(300);
                while(suspended) {
                    System.out.println("suspended");
                    Thread.sleep(50);
                }
            }
        } catch (final InterruptedException e) {
            System.out.println("Thread " +  threadName + " interrupted.");
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }

    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }

    void suspend() {
        suspended = true;
    }

    void resume() {
        suspended = false;
        notify();
    }

    public static void main(final String[] args) throws InterruptedException  {
        final SuspendDemo R1 = new SuspendDemo( "Thread-1");
        R1.start();
        R1.suspend();
        Thread.sleep(500);
        R1.resume();
    }
}

由于:

> Creating Thread-1 
> Starting Thread-1 
> Running Thread-1 
> Thread: Thread-1
> suspended
> suspended
> suspended
> suspended
> Thread: Thread-1
> Thread: Thread-1
> Thread: Thread-1

suspend标志是一个本机布尔值,因此写入它是一个原子操作,因此你可以不进行任何同步。 我建议在使用synchronized之前完全理解并发编程和Java使用的监视器并发模型。我发现使用synchronize(this)块很难维护并且容易出错。

下一个示例使用 wait() notifyAll()解决了问题。请注意使用synchronized方法来锁定线程对象的监视器而不是同步(this)块。

public class SuspendDemo implements Runnable {
    public Thread t;
    private final String threadName;
    boolean suspended = false;
    SuspendDemo(final String name){
        threadName = name;
        System.out.println("Creating " +  threadName );
    }

    @Override
    public void run() {
        System.out.println("Running " +  threadName );
        try {
            while (true) {
                System.out.println("Thread: " + threadName);
                // Let the thread sleep for a while.
                Thread.sleep(300);
                work();
            }
        } catch (final InterruptedException e) {
            System.out.println("Thread " +  threadName + " interrupted.");
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }

    synchronized protected void work() throws InterruptedException {
        while(suspended) {
            System.out.println("suspended");
            wait();
            System.out.println("resumed");
        }
    }

    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }

    synchronized void suspend() {
        suspended = true;
        notifyAll();
    }

    synchronized void resume() {
        suspended = false;
        notifyAll();
    }

    public static void main(final String[] args) throws InterruptedException  {
        final SuspendDemo R1 = new SuspendDemo( "Thread-1");
        R1.start();
        R1.suspend();
        Thread.sleep(500);
        R1.resume();
    }
}