旧的C ++程序员,Java新手,需要有关Java多线程和事件的帮助

时间:2013-01-30 11:15:35

标签: java multithreading event-handling thread-synchronization

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

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

所以,在Java并发海上挣扎了好几天之后,在“原始”线程上花了这么多工作之后,我会请求一个建议,也许还有一些样本。

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

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

? 我真的不知道这些点是否取决于我选择的对象,所以我列出它们只是为了避免重新做一切,因为我不清楚。

感谢。

2 个答案:

答案 0 :(得分:2)

如果你有一些主线程只需要从其他线程接收事件(就像服务器套接字那样),一些blocking queue可能是一个解决方案。主线程可以在循环中调用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);
      }    
    }
 });

答案 1 :(得分:-1)

我会根据singleton创建一个port-lietening线程,可能还有一些静态(synchronized!)访问器。

在你的案例中,线程之间进行通信的良好界面是Listener/Observer pattern - 它应该足够多才能解决你的问题。

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