0

抱歉我的格式不好。我正在使用记事本编写程序。

这是一个工作代码。我唯一的问题是,我已经读过通知和等待必须在同步块中使用。但是,在以下示例中,在同步块中未使用等待和通知,并且仍然没有引发错误。

class counthrd implements Runnable {

    Thread thrd;
    String x;
    counthrd cnt1;

    counthrd() {
    }
    boolean suspended;
    boolean stopped;

    counthrd(String s, counthrd cnt1) {
        thrd = new Thread(this, s);
        this.cnt1 = cnt1;
        thrd.start();
        x = s;
    }

    public void run() {

        try {
            System.out.println("Starting " + thrd.currentThread().getName());
            for (int i = 1; i < 100; i++) {
                System.out.print(i + "  ");
                if ((i % 10) == 0) {
                    System.out.println();
                    Thread.sleep(500);
                }
//synchronized(cnt1){
                while (suspended) {
                    System.out.println("going to wait mode");
                    wait();
                    notify();
                }
//}
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    synchronized void suspendme() {
        suspended = true;
        notify();
    }

    synchronized void resumeme() {
        suspended = false;
        notify();
    }
}

class counter {

    public static void main(String args[]) throws InterruptedException {
        counthrd cnt1 = new counthrd();
        counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

        Thread.sleep(1000);
        System.out.println("going to wait mode");
        cnt1.suspendme();
        Thread.sleep(1000);
        System.out.println("resuming");
        cnt1.resumeme();
        Thread.sleep(1000);
    }
}
4

1 回答 1

3

我的评论。由于IllegalMonitorStateException从不被抛出,我们知道它wait永远不会被调用。

请注意,您有两个实例counthrd...

counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

suspendme查看您正在调用哪个实例resumeme

Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);

cnt1使用您的无参数构造函数进行初始化,如下所示:

counthrd() {
}

关键是它cnt1从来没有真正开始自己的线程。它从不做任何事情,真的。cnthrd1是启动线程的线程,如下所示:

counthrd(String s, counthrd cnt1) {
    thrd = new Thread(this, s);
    this.cnt1 = cnt1;
    thrd.start();
    x = s;
}

需要说明的是,它是一个实例字段,而不是在andsuspended之间共享。修改不会导致进入“等待模式”。永远不会被调用,因此永远不会抛出异常。cnt1cnthrd1cnt1.suspendedcnthrd1wait

为了演示,请尝试调用suspendmeand resumemeon cnthrd1,而不是... :-)

C:\dev\scrap>javac counter.java

C:\dev\scrap>java counter
Starting thrd 1
1  2  3  4  5  6  7  8  9  10
11  12  13  14  15  16  17  18  19  20
going to wait mode
going to wait mode
java.lang.IllegalMonitorStateException
resuming

话虽如此,我想我会建议你做一些你的代码应该做的事情。

  1. 声明suspendedvolatile如果没有一些明确的内存排序保证,则 无法保证何时或什cnthrd1至读取suspended.
  2. 抛弃cnt1字段和实例;他们没有理由。也摆脱那个空的构造函数。
  3. Thread.currentThread是静态方法;您不需要为此使用实例。除此之外,这里thrd保证相等Thread.currentThread
  4. counthrd.x等于thrd.getName; 为什么不直接使用x呢?
  5. 使用一些更好、更具描述性的名称。例如,而不是x,为什么不name呢?而不是thrd,为什么不thread呢?而不是counthrd,为什么不CountingThread呢?
  6. 你只需要打电话notifyresumeme不需要suspendme。(事实上​​,调用可能notifysuspendme意外触发InterruptedExceptionif 线程正在休眠,即 when (i % 10) == 0
  7. 你也不想notifywhile (suspended)循环中。现在,您的while循环实际上也可以变成if语句。
  8. 如前所述,您需要synchronized (this)围绕调用while.
  9. 避免在构造函数中执行真正的逻辑,例如thrd.start().
  10. suspend不需要synchronizedresume也不需要synchronized是;只有waitandnotify调用需要它。

您可以在此处找到可以正常工作的示例的修改版本。

于 2012-08-19T03:22:16.740 回答