2

我正在将使用串行端口的 C++ 程序(更准确地说是 Borland“组件”)“转换”为 Java。该程序使用一个线程来侦听串行端口,并在接收到给定的“事件字符”之一(它可能是回车、ACK、NACK ......)或当用户定义数量的字符被接收。

在尝试用 Java 转换它时,我学到了一些关于线程的知识,让它半工作。我仍然需要了解如何将事件从侦听线程引发到主线程......然后我了解到 Executors 的存在,这似乎是正确的方法,因为用户可以关闭、重新打开或更改多次使用端口并每次创建一个新线程似乎是一种不好的做法。

因此,在 Java 并发海中挣扎了好几天之前,在“原始”线程上花费了这么多工作之后,我会寻求建议,也许还有一点样本。

我应该使用什么样的对象(我看到有各种类型的执行器)来拥有一个串行侦听器:

  • 能够向主线程抛出一个事件以传递接收到的字符数组
  • 可以暂停和重新启动(并且可以在暂停时指向不同的输入流......我的意思是我可以在暂停时调用它的一些方法)
  • 它会在不需要时被销毁(用户可以选择使用套接字,因此不再需要监听器)

? 我真的不知道其中一些点是否取决于我将选择的对象,所以我将它们全部列出,以避免再次重新做所有事情,因为我不清楚。

谢谢。

4

2 回答 2

2

如果您有一些主线程必须从其他线程接收事件(很像服务器套接字),那么一些阻塞队列可能是一种解决方案。主线程可以takeLast在循环中调用 - 这将暂停它,直到任何其他线程调用putFirst,为同一队列提供一个值。(SynchronousQueue将停止提供线程,直到主线程准备好,或者ArrayBlockingQueue支持给定大小的队列)。

通过这样的设置,主线程也不能是 GUI 线程。如果您需要从中触摸标签或按钮等界面组件,请使用invokeAndWait 。

 final BlockingQueue q = new ArrayBlockingQueue(3); 

 new Thread() {
    public void run() {
       while (have_some_messages()) { 
         q.putFirst("Hey!");
       }
    }
 }.start();

 new Thread() {
    public void run() {
       while (also_have_some_messages()) { 
         q.putFirst("Boo!");
       }
    }
 }.start();

 // Main thread will print both Hey and Boo:
 while (must_keep_running()) {
   Object serveIt = q.takeLast();
   System.out.println(serveIt);
 }

如果主线程是 Swing 线程(您说带有 Swing 控件的 JFrame),请在此处添加一个按钮以启动服务线程:

Runnable service = new Runnable() {
  public void run() {
    try {
      while (must_keep_running()) {
    Object serveIt = q.takeLast();
    System.out.println(serveIt);
  }
} finally {
// Re-enable the start button when the service thread exits:
  SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          bStart.setEnabled(true);
            }
          });
        };
      }
    };

 JButton bStart = new JButton("Start ..");
 bStart.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
         new Thread(service).start();
         bStart.setEnabled(false);
      }    
    }
 });
于 2013-01-30T11:44:48.147 回答
-1

我会基于一个可能带有一些静态(同步!)访问器的单例来创建端口监听线程。

在您的情况下,用于在线程之间进行通信的良好接口将是侦听器/观察者模式- 它应该足够通用以解决您的问题。

由于您是 Java 初学者,因此提示:从无线程开始,只需使用非阻塞 IO。然后 - 只有在一切正常之后 - 考虑使用多个线程。并且只有在您遇到性能问题时才这样做。

于 2013-01-30T11:21:14.500 回答