java - 事件调度线程同步

标签 java multithreading swing junit

更好地了解 EDT 同步如何运作

我创建了一个简单的 JUnit3 测试用例 - 见下文。目标是等待两个事件:

  1. 要创建的 GUI/JFrame
  2. 文本字段的修改

首先,我尝试对相应的 boolean 锁对象进行 wait() 调用,但没有按预期工作。然后我尝试循环等待 boolean 锁内容。这两种方法都没有达到我的预期。

需要如何修改下面的代码才能获得预期的等待行为?

JUnit 测试用例

package com.bitplan.test.common;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import junit.framework.TestCase;

/**
 * test the event dispatching thread handling
 * 
 * @author wf
 *
 */
public class TestEDT extends TestCase {


  private JTextField field;
  private  Boolean modified=new Boolean(false);
  private  Boolean created=new Boolean(false);

  /**
   * test UI handling
   * 
   * @throws InterruptedException
   */
  public void testUI() throws InterruptedException {
    // see
    // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
    synchronized(created) {
      created.wait();
      /**
      while(!created.isTrue()) {
        Thread.sleep(10);
      } */
    }
    field.getDocument().addDocumentListener(new DocumentListener() {
      public void flagModification() {
        synchronized(modified) {
          modified=true;
          modified.notify();
        }      
      }
      public void insertUpdate(DocumentEvent e) {
        flagModification();
      }

      @Override
      public void removeUpdate(DocumentEvent e) {     
        flagModification();
      }

      @Override
      public void changedUpdate(DocumentEvent e) {
        flagModification();        
      }
    });
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        updateField("fieldcontent");
      }
    });
    synchronized(modified) {
      // https://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java?noredirect=1&lq=1
      modified.wait();
      /**
      while(!modified) {
        Thread.sleep(10);
      } */
    }
  }

  /**
   * update the field with the new content;
   * 
   * @param newContent
   */
  protected void updateField(String newContent) {
    field.setText(newContent);
  }

  /**
   * create and show the given gui
   */
  protected void createAndShowGUI() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("Example GUI");
    JPanel panel = new JPanel();
    field = new JTextField(30);
    panel.add(field);
    frame.setContentPane(panel);
    frame.pack();
    frame.setVisible(true);
    synchronized(created) {
      created=true;
      created.notify();
    }
  }
}

最佳答案

如果使用“Lock”类,则该方法有效。最初我使用了 boolean 值,但它不起作用,因为这些锁对象被赋值替换,例如

created=true. 

将创建一个新的单独的 boolean 对象,因此created.notify()会向另一个对象发出信号,并且不会停止主线程中的等待。

锁定版本有效。我已将问题的代码更改回原来的错误 boolean 版本以表明这一点。

package com.bitplan.test.common;

import java.awt.Frame;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import junit.framework.TestCase;

/**
 * test the event dispatching thread handling
 * 
 * @author wf
 *
 */
public class TestEDT extends TestCase {

  public static class Lock {

    boolean value;

    public Lock(boolean value) {
      super();
      this.value = value;
    } 
    /**
     * @return the value
     */
    public boolean isTrue() {
      return value;
    }

    /**
     * @param value the value to set
     */
    public void set(boolean value) {
      this.value = value;
    }
  }
  private JTextField field;
  private Lock modified=new Lock(false);
  private Lock  created=new Lock(false);

  /**
   * test UI handling
   * 
   * @throws InterruptedException
   */
  public void testUI() throws InterruptedException {
    // see
    // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
    synchronized(created) {
      while(!created.isTrue())
        created.wait();
    }
    field.getDocument().addDocumentListener(new DocumentListener() {
      public void flagModification() {
        synchronized(modified) {
          modified.set(true);
          modified.notify();
        }      
      }
      public void insertUpdate(DocumentEvent e) {
        flagModification();
      }

      @Override
      public void removeUpdate(DocumentEvent e) {     
        flagModification();
      }

      @Override
      public void changedUpdate(DocumentEvent e) {
        flagModification();        
      }
    });
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        updateField("fieldcontent");
      }
    });
    synchronized(modified) {
      while(!modified.isTrue())
      // http://stackoverflow.com/questions/2536692/a-simple-scenario-using-wait-and-notify-in-java?noredirect=1&lq=1
        modified.wait();
    }
  }

  /**
   * update the field with the new content;
   * 
   * @param newContent
   */
  protected void updateField(String newContent) {
    field.setText(newContent);
  }

  /**
   * create and show the given gui
   */
  protected void createAndShowGUI() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setTitle("Example GUI");
    JPanel panel = new JPanel();
    field = new JTextField(30);
    panel.add(field);
    frame.setContentPane(panel);
    frame.pack();
    frame.setVisible(true);
    synchronized(created) {
      created.set(true);
      created.notify();
    }
  }
}

关于java - 事件调度线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38372229/

相关文章:

python - 当在队列中启动多个线程时,哪个线程从堆栈中取出第一个

java - 从 SwingWorker 线程获取结果后,具有特定 JRadioButton 的 JPanel 不会更新

java - 如何初始化Class<?扩展我的类>

c# - C# 中的线程问题(字段初始化程序无法引用非静态字段等)

java - 如何在OnCreate中自动打开网络?

java - 当多个线程同时请求加载同一个类时会发生什么?

java - JFrame 的内容不显示

java - 调整 JscrollPane 的大小

java - 无法通过测试用例从 src/main/resources 访问文件

java - 为什么我的解决方案无法找到二叉树的最小深度?