2

我有一个 Lanterna 终端应用程序。

使用线程,我想用不同的面板填充一个窗口并相应地读取键输入。

使用:

thread1 = new ModuleThreads(screen,"Locations","addRightPanel");
thread2 = new ModuleThreads(screen,"Commands","addCenterPanel");
thread1.start();
thread2.start();

第一个线程在右侧面板中显示“位置”菜单。菜单包含:“按 a 退出。” 线程工作。出现菜单,按 a 退出程序。

现在第二个线程没有出现,也没有听到按下的匹配键:“按 b 退出。” 此外,我使用反射能够轻松更改菜单内容。(无论如何,它是一个个人项目......:))问题是只有第一个 thread1 显示在 ui 中。反射只是工作。thread2 本身工作得很好。但就像一个单一的线程。

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();
}
}

}

我究竟做错了什么?为什么只有线程 1 或线程 2 出现,而​​不是同时出现两个关键侦听器?

4

2 回答 2

1

1)你为什么要覆盖这样的start()方法Thread

public void start(){    
}

通过这样做,您可以防止run()调用该方法。从 javadoc :

无效 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因为它更适合在线程外部决定何时启动线程。

于 2017-01-14T15:33:32.143 回答
0

我想我找到了解决方案:

在不同线程中使用和修改相同对象的链接

所以而不是:

        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();

我认为这个原则可以解决问题吗?

于 2017-01-16T16:43:12.707 回答