8

誰かが私にJavaのwait()とnotify()機能を示す良い小さな例を提供してくれませんか。以下のコードを試してみましたが、期待したものが表示されません。

public class WaitDemo {
    int i = 10;

    int display() {
        System.out.println("Lexmark");
        i++;
        return i;
    }
}
public class ClassDemo1 extends Thread {

    private WaitDemo wd = new WaitDemo();

    public static void main(String[] args) {
        ClassDemo1 cd1 = new ClassDemo1();
        ClassDemo1 cd2 = new ClassDemo1();
        cd1.setName("Europe");
        cd2.setName("America");
        cd1.start();
        cd2.start();

    }

    synchronized void display() {
        System.out.println("Hello");
        notifyAll();
    }

    public void run() {

        synchronized (this) {
            try {
                {
                    notify();
                    System.out.println("The thread is " + currentThread().getName());
                    wait();
                    System.out.println("The value is " + wd.display());
                }
            } catch (InterruptedException e) {

            }

        }
    }
}

問題は、クラスWaitDemoのメソッドが実行されておらず、私の考えによれば、wait()後のSOPが実行される必要があることです。これについて私を助けてください。

4

7 に答える 7

3

ブロックには 2 つのレベルの中括弧{がありますtry。内部セット (何もしないように見える) を削除すると、問題は解決しますか?

周りにはいくつかの例があり、そのすべてが使用法を示しています。最後のリンクは、役立つ一連の結果です。より具体的なことが必要な場合は、アプリが何をしようとしているのかをお知らせください。状況により具体的な例を見つけることができます。

于 2011-12-02T15:30:24.507 に答える
0

問題は、Thread クラスの 2 つのインスタンスを作成していることです。したがって、wait() が呼び出されると、それは 2 つの異なるインスタンス上にあります。どちらのインスタンスにも、モニターに対して競合している別のスレッドがなく、また、スレッドを待機状態から復帰させるために notifyAll() を呼び出す別のスレッドもありません。

したがって、開始した各スレッドは永久に (または他の理由で中断されるまで) 待機します。

複数のスレッドが同じモニターにアクセスする必要があるため、問題のコードが実際にはスレッドではなく、単にスレッドによって使用されているコードを作成することから始めます。

@normalocity はすでに複数の例へのリンクを提供しています。

于 2011-12-02T15:58:53.223 に答える
0

SCCEを含めるようにこの回答を更新しました。

ワーカーは、WorkerPauseManager で pauseIfNeeded を呼び出します。ワーカー スレッドが pauseIfNeeded() を呼び出したときにマネージャーが一時停止している場合は、wait() を呼び出します。これは、待機中のオブジェクトに対して別のスレッドが notify() または notifyAll() を呼び出すまで待機するように呼び出しスレッドに指示します。これは、Swing イベント ディスパッチ スレッドがマネージャで play() を呼び出し、次にマネージャが notifyAll() を呼び出すときに発生します。

wait() または notify() を呼び出しているオブジェクトに同期ロックが必要であることに注意してください。WorkerPauseManager のメソッドは同期されているため、同期されたすべてのメソッドは WorkerPauseManager 自体で同期ロックを取得しています。

import javax.swing.*;
import java.awt.event.ActionEvent;

/**
 * @author sbarnum
 */
public class WorkerPauseManagerTest {
    public static void main(String[] args) {
        final WorkerPauseManager pauseManager = new WorkerPauseManager();
        new Worker("Worker 1", pauseManager).start();
        new Worker("Worker 2", pauseManager).start();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") {
                    public void actionPerformed(final ActionEvent e) {
                        JToggleButton source = (JToggleButton) e.getSource();
                        if (source.isSelected()) {
                            pauseManager.start();
                            source.setText("Pause");
                        } else {
                            pauseManager.pause();
                            source.setText("Play");
                        }
                    }
                });
                playPauseButton.setSelected(true); // already running
                JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE);
                System.exit(0);
            }
        });

    }

    private static class Worker extends Thread {
        final String name;
        final WorkerPauseManager pauseManager;

        public Worker(final String name, final WorkerPauseManager pauseManager) {
            this.name = name;
            this.pauseManager = pauseManager;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                try {
                    pauseManager.pauseIfNeeded();
                    System.out.println(name + " is running");
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static final class WorkerPauseManager {

        private boolean paused;

        public synchronized void pauseIfNeeded() throws InterruptedException {
            if (paused) wait();
        }

        public synchronized void pause() {
            this.paused = true;
        }

        public synchronized void start() {
            this.paused = false;
            notifyAll();
        }
    }
}
于 2011-12-02T16:44:03.283 に答える
-2
/*
 *  the below program is like 
 * tread t1 will first run , and it comes to "notify()" method
 * there are no threds waiting bcoz this is the first thread.
 * so it will not invoke any other threads. next step is "wait()" method
 *will be called and the thread t1 in waiting state. next stament 
 * "System.out.println("The value is ..."+wd.display());" will not be  executed
 * because thread t1 is in waiting state.
 * 
 * thread t2 will run ,and it comes to "notify()" method ,there is already 
 * thread t1 is in waiting state ,then it will be invoked.now thread t1 will
 * continue execution and it prints the statement "System.out.println("The value is ..."+wd.display())"
 * and thread t2 will be in waiting state now.
 * 
 * if you uncomment "notifyAll()" method then, after t1 thread completes its execution
 *then immediately "notifyAll()" method will be called,by that time thread t2 is 
 * already in waiting state , then thread t2 will be invoked and continues execution.
 *or
 * if any other threadds are in waiting state all those threads will be invoked.
 */
package threadsex;

/**
 *
 * @author MaheshM
 */
/**
 * @param args the command line arguments
 */
public class WaitNotifyNotifyAllDemo implements Runnable {
    WaitDemo wd = new WaitDemo();

    public static void main(String[] args) {
        WaitNotifyNotifyAllDemo cd1 = new WaitNotifyNotifyAllDemo();
        Thread t1 = new Thread(cd1);
        t1.setName("mahi1");
        Thread t2 = new Thread(cd1);
        t2.setName("mahi2");
        t1.start();         
        t2.start();
    }

    @Override
    public void run() {
        synchronized (this) {
            try {

                System.out.println("The thread is=" + 
                        Thread.currentThread().getName());
                notify();
                wait();
                System.out.println("The value is ..." + wd.display());
                //         notifyAll();

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
于 2012-10-01T11:49:52.420 に答える