我有一个Lanterna终端应用程序。
对于线程,我想用不同的面板填充一个窗口并相应地读取键输入。
使用:
public class ModuleThreads extends Thread{
Screen screen;
String myclass,panel;
Class noparams[]={};
Class moduleClass,panelClass;
Class[] paramScreen;
Class[] myPanelClass;
Constructor constructor,moduleConstructor;
Object moduleObject,panelObject;
Method panelGetView,panelMethod,moduleMethod;
Panel mypanel;
private Thread thread1;
public ModuleThreads(Screen screen,String myclass,String panel){
this.screen=screen;
this.myclass=myclass;
this.panel=panel;
//class aanmaken van Screen.class
paramScreen = new Class[1];
paramScreen[0] = Screen.class;
myPanelClass = new Class[1];
myPanelClass[0] = Panel.class;
thread1 = new Thread(this);
thread1.start();
try{
moduleClass = Class.forName("app.modules."+this.myclass);
//package name er voor plakken.
moduleObject = moduleClass.newInstance();
moduleMethod =
moduleClass.getDeclaredMethod("readInput",paramScreen);
moduleConstructor = moduleClass.getConstructor();
panelClass = Class.forName("app.view.MainView");
constructor = panelClass.getConstructor(Screen.class);
panelObject= constructor.newInstance(this.screen);
panelGetView = moduleClass.getDeclaredMethod("getView",noparams);
panelMethod =
panelClass.getDeclaredMethod(this.panel,myPanelClass);
mypanel = (Panel) panelGetView.invoke(moduleObject,null);
panelMethod.invoke(panelObject, mypanel);
moduleMethod.invoke(moduleObject,this.screen);
}catch(Exception e){
e.printStackTrace();
}
}
public void start(){
}
@Override
public void run(){
try{
mypanel = (Panel) panelGetView.invoke(moduleObject,null);
panelMethod.invoke(panelObject, mypanel);
moduleMethod.invoke(moduleObject,this.screen);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
第一个主题在右侧面板中显示"位置"菜单。 菜单包含: "按a退出。"线程有效。出现菜单,然后按退出程序。
现在第二个Thread没有出现也没有按下匹配的键:"按b退出。" 此外,我使用反射可以轻松地更改菜单内容。(无论如何,这是一个个人项目... :)) 问题是只有第一个thread1显示在ui中。 反思才有效。 本身thread2工作正常。但就像一个单一的线程一样。
{{1}}
我做错了什么?为什么只有线程1或线程2出现,而不是两者都出现在两个关键的监听器上?
答案 0 :(得分:1)
1)为什么要覆盖start()
这样的Thread
方法:
public void start(){
}
通过这样做可以防止调用run()
方法。
来自javadoc:
void java.lang.Thread.start()
使该线程开始执行; Java虚拟机调用 这个线程的run方法
2)你开始每个线程两次。
thread1 = new ModuleThreads(screen,"Locations","addRightPanel");
thread2 = new ModuleThreads(screen,"Commands","addCenterPanel");
thread1.start();
thread2.start();
和
public ModuleThreads(Screen screen,String myclass,String panel){
...
thread1 = new Thread(this);
thread1.start();
...
你应该开始一次你的线程。您可以删除在start()
构造函数中执行的ModuleThreads
调用,因为在线程应该启动时更适合在线程之外做出决定。
答案 1 :(得分:0)
我想我找到了一个解决方案:
link in using and modifying same object in different threads
所以而不是:
thread1 = new ModuleThreads(screen,"Locations","addRightPanel");
thread2 = new ModuleThreads(screen,"Commands","addCenterPanel");
thread1.start();
thread2.start();
我会有类似的东西:
Screen screen = new TerminalScreen(terminal);
thread1 = new ModuleThreads()
{ public void run (){screen.updatePanels("Locations","addRightPanel");
screen.readInput();
}
};
thread2 = new ModuleThreads()
{ public void run (){screen.updatePanels("Commands","addCenterPanel");
screen.readInput();
}
};
thread1.start();
thread2.start();
我认为这个原则可以解决问题吗?