我有一个带有多线程的TCP服务器,可以从cli处理它。
现在我想为它编写一个GUI,以便我可以轻松地启动,监视,管理和退出该多线程服务器的特定实例。首先我想到了JTable,这也是我的第一个问题:
在JTable内的多个套接字(而不是线程)上处理多个serverthread是一种好方法(甚至可能),我是否能够根据socketactivities向其发送数据以更新各行?我的意思是当每一行代表一个正在运行的serverthread时,用户应该能够点击它,开始一个新的(将被添加到列表中)看到一个字段中的socketstatus(无论是什么),看看有多少客户端是连接的,甚至可以通过该表停止特定的线程?
我的第二个问题是:
当我按照上面描述的方式开始实现它时,当我用另一个接口更新活动JPanel并再次切换回来时,jtable和正在运行的线程会发生什么?例如,我有一个接口用于概述所有实例,另一个接口用于单个实例的详细信息。是否所有线程都会被中断,或者之后是否可以与Table通信?或者使用cardLayout更好吗?
当我在cardlayout上更换卡并且在这张卡上运行时(例如,带有运行套接字线程的JTable)它们是否会被中断或停止,或者我是否可以更新JTable中的statusdata?因此套接字应该能够在所有表上写入和更新数据。
现在是我的最后一个问题,感谢阅读这么长时间。在尝试发现上述所有问题的答案时,我尝试了一个简单的JPanel切换框架,每个面板上有一个JTextarea,写入100行,间隔1000ms。然后我想切换面板,看看那个任务是否被中断了。不幸的是,我甚至无法将其付诸实践。
在外部类MyPanel中,我正在启动具有单独配置的JPanel并将其添加到主框架中。
for循环仅用于测试:
class MyPanel extends JPanel {
public static JTextArea tArea;
public MyPanel(String config) {
JButton testButton = new JButton(config);
add(testButton);
tArea = new JTextArea();
JScrollPane scroll = new JScrollPane(tArea);
add(scroll, BorderLayout.CENTER);
for (int i = 0 ; i < 50 ; i ++ ) {
tArea.append("test \n") ;
try { Thread.sleep(2000); } catch(InterruptedException ie) {}
}
setVisible(true);
revalidate();
repaint();
}
}
但我认为,这是完全错误的,因为我在重新验证和重新绘制之前调用它:(并且在大型机内我想以这种方式启动它:
JMenuItem menuItem = new JMenuItem("Test");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
MyPanel dynamicPanel = new MyPanel("Test");
contentContainer.removeAll();
contentContainer.add(dynamicPanel);
contentContainer.revalidate();
contentContainer.repaint();
}
});
答案 0 :(得分:2)
首先你需要知道,Swing是一个单线程框架,并不是线程安全的。这意味着所有与UI的更新和交互必须在UI线程(事件调度线程)中进行,请参阅Concurrency in Swing
在JTable中的多个套接字(而不是线程)上处理多个serverthread是一种好方法(甚至是可能的),我是否能够根据socketactivities向其发送数据以更新各行?我的意思是当每一行代表一个正在运行的serverthread时,用户应该能够点击它,开始一个新的(将被添加到列表中)看到一个字段中的socketstatus(无论是什么),看看有多少客户端是连接的,甚至可以通过该表停止特定的线程?
老实说,我认为这不重要,你遇到的问题是从你的线程/套接字获取信息到你的UI。我要考虑做的是拥有Thread
,其唯一目的是轮询所有其他线程/套接字以获取信息,然后将该信息与UI同步,确保不会破坏流程中单个线程的Swing规则。根据您的设计,SwingWorker
可能是一个不错的选择。
我不会考虑让每个线程单独向UI发送信息的原因是,这将是一个非常好的方法来压倒EDT并导致它滞后,同时它试图处理大量数据系统可能会创建
当我开始按照上面描述的方式实现它时,会发生什么 当我更新活动的JPanel时,jtable和正在运行的线程 用另一个界面再切换回去?例如,我有一个 接口,用于概述所有实例和另一个实例 关于它的单个实例的详细信息。将所有线程中断或 他们可以再次与桌子沟通吗?或者它更好 使用cardLayout?
当我在卡片布局上更换卡片时,这张卡片就是这样的 运行(例如,运行socketthreads的JTable)将是 中断或停止或我可以更新JTable中的statusdata 了吗?所以套接字应该能够写入和更新数据 表格全部。
根据我上面给出的描述,您在后台运行的线程基本上什么都不会发生,因为它们与UI断开连接。 &#34;民意调查&#34;线程仍然会运行,并仍然会向表发送更新(我希望通过TableModel
),但是,因为它在屏幕上实际上不可见,所以它不会被绘制和& #34;应该&#39; T&#34;对系统的性能产生不利影响。
这提出了一个&#34;州&#34;某种模式。该模型实际上可以用于描述单个线程的状态,然后可以通过&#34;状态&#34;来管理。 manager,它允许您访问此信息(以及实际线程)。轮询线程将从正在运行的线程/套接字获取信息并更新相关的&#34;状态&#34;该线程的模型,这意味着您可以挂起整个UI,并知道在访问它时,它只能在EDT的上下文中修改 - 没有死锁或竞争条件。作为一个想法
现在是我的最后一个问题,感谢阅读这么长时间。在尝试时 发现上述所有问题的答案,我试过一个简单的问题 JPanel在每个写入100的Panel上切换带有JTextarea的Frame 在1000毫秒之间休息的线。然后我想切换面板 并查看该任务是否被中断。该死的我是一个菜鸟,我不能 甚至把它带到了工作中。
在外部类MyPanel中,我正在使用个人启动JPanel 配置并将其添加到主框架。
那是因为你的代码阻塞了事件调度线程,事件调度线程负责处理事件队列,事件队列也带有重绘事件(除其他外),这意味着,当循环运行时,用户界面无法更新(或与之互动)。
使用SwingWorker
可以更好地提供代码。
有关详细信息,请参阅Concurrency in Swing和Worker Threads and SwingWorker