有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如果我有一个可运行线程和一个实现线程,如何使用wait()和notify()?

我想在第一个线程完成后开始第二个线程。但是,如果线程的实现方式不同,我不知道如何使用wait()/notify()函数。 第一次尝试在单独的类中使用它,但之后我无法让第一个线程在完成时发出信号

public class Oblig1 {

  static void threadMessage(String message) {
    String threadName =
        Thread.currentThread().getName();
    System.out.format("%s: %s%n",
                      threadName,
                      message);
  }

  private boolean start = false;

  public void StartThread(){
    start = true;
  }

  class Thread1 implements Runnable{
    private int X;
    Thread2 obj = new Thread2(5);

    public Thread1(int x) {
      X = x;
    }

    public synchronized void run() {
      for (int i=1; i<21; i++) {
        System.out.print(X*i + " ");

        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
          threadMessage("I wasn't done!");
        }
      }

      StartThread();
      notifyAll();
    }
  }

  class Thread2 extends Thread {
    private int X;

    public Thread2(int x) {
      X = x;
    }

    public synchronized void run() {    
      while (!start){
        try {
          wait();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

      for (int i=1; i<21; i++) {
        System.out.print(X*i + " ");
          try {
            Thread.sleep(500);
          } catch (InterruptedException e) {
            threadMessage("I wasn't done!");
          }
        }

        notifyAll();
      }
    }


    public static void main(String [ ] args) {

        int inputT1 = 3;
        int inputT2 = 5;


        Thread t1 = new Thread(new Thread1(inputT1));
        Thread t2 = new Thread(new Thread2(inputT2));

        t1.start();
        t2.start();
  }
}

共 (3) 个答案

  1. # 1 楼答案

    您等待某个对象并通知某个对象(在当前代码中,您没有指定对象,所以它是this)。因此,线程本身调用notify,但没有人在等待它。Thread2正在等待自己,但没有人唤醒它(因为没有人在Thread2的这个实例上调用notify)

    要唤醒Thread2,需要在该对象上调用notify(这是this),这样Thread1就应该调用obj。notify()(因为在代码中obj是Thread2)

    但是,它仍然无法工作,因为您没有将Thread2实例传递给Thread1(您只是在Thread1中创建了一个新实例),所以您通知的Thread2刚刚创建,从未启动。主线程中的线程2已启动,但从未收到通知

    对代码的可能修复

    static class Thread1 extends Thread {
    private int X;
    final Thread2 second;
    
    public Thread1(int x,Thread2 second) {
     X = x;
     this.second = second;
    }
    
    public void run() {
    
        for(){
        //....    
        }
    
        second.start = true;
        second.notify();
    }
    }
    
    static class Thread2 extends Thread {
    private int X;
    public boolean start = false;
    
    public Thread2(int x) {
     X = x;
    }
    
    public void run() {
    
        while(!start){
            synchronized(this) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            }
        }
    
        for(){
            ....
        }
    }
    }
    
    
    public static void main(String [ ] args)
    {
    
            int inputT1 = 3;
            int inputT2 = 5;
    
            Thread2 t2 = new Thread2(inputT2);
            Thread1 t1 = new Thread1(inputT1,t2);
    
    
            t1.start();
            t2.start();
    }
    
  2. # 2 楼答案

    wait()notify()方法是低级原语,最好避免使用高级并发API。滚动自己的并发代码可能会有问题(例如,代码中的start字段需要易变!)

    一个简单的解决方法是使用CountDownLatch。替换这个:

    private boolean start = false;
    

    有了这个:

    private final CountDownLatch latch = new CountDownLatch(1);
    

    然后,您将调用notifyAll(),而不是调用latch.countDown();

    Thread2的run方法如下所示:

    public void run() {
      latch.await(); 
    
      for (int i=1; i<21; i++) {
        System.out.print(X*i + " ");
        try {
           Thread.sleep(500);
        } catch (InterruptedException e) {
          threadMessage("I wasn't done!");
        }
      }
    
      threadMessage("Done");
    }
    
  3. # 3 楼答案

    使用lock/notify一个接一个地运行两个线程的示例:

    public class Thread2Test {
    public static void main(String[] args)
    {
        final Object sync = new Object();
        final Object lock = new Object();
    
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(lock) {
                    synchronized(sync) {
                        sync.notify(); // Notify main() to let it start t2.
                    }
    
                    for (int n=0; n<10; n++)
                    {
                        System.out.println(n);
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                        }
                    }
                    System.out.println("t1 finished.");
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2 started...");
                synchronized(lock) {
                    // don't need to do anything but wait for lock to be released
                }
                char c = 'a';
                for (int n=0; n<10; n++)
                {
                    System.out.println(c);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                    }
                    c++;
                }
                System.out.println("t2 finished.");
            }
        });
    
        try {
            System.out.println("Wait for t1 to start...");
            synchronized(sync) {
                t1.start();
                sync.wait();
            }
        } catch (InterruptedException e) {
        }
        System.out.println("end wait");
        t2.start();
    }
    

    请注意,sync对象用于确保t1总是在t2之前启动