Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程不与Laterna一起工作_Java_Multithreading_Terminal_Lanterna - Fatal编程技术网

Java 线程不与Laterna一起工作

Java 线程不与Laterna一起工作,java,multithreading,terminal,lanterna,Java,Multithreading,Terminal,Lanterna,我有一个Lanterna终端应用程序 使用线程,我想用不同的面板填充一个窗口,并相应地读取键输入 使用: thread1 = new ModuleThreads(screen,"Locations","addRightPanel"); thread2 = new ModuleThreads(screen,"Commands","addCenterPanel"); thread1.start(); thread2.start(); 第一个线程在右侧面板中显示“位置”菜单。 菜单包含: “按a键退

我有一个Lanterna终端应用程序

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

使用:

thread1 = new ModuleThreads(screen,"Locations","addRightPanel");
thread2 = new ModuleThreads(screen,"Commands","addCenterPanel");
thread1.start();
thread2.start();
第一个线程在右侧面板中显示“位置”菜单。 菜单包含: “按a键退出。”线程工作。出现菜单,按a退出程序

现在第二个线程不会出现,也不会监听匹配的按键:“按b退出” 此外,我还使用了反射功能,可以轻松地更改菜单内容 问题是ui中只显示第一个thread1。 反射就行了。 就其本身而言,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,而不同时显示两者?

1)为什么要重写
thread
start()
方法,如下所示:

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


你应该一次启动你的线程。您可以删除在
ModuleThreads
构造函数中执行的
start()
调用,因为它更适合在线程外部决定何时启动线程。

我想我找到了一个解决方案:

因此,不是:

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

我认为这个原则可以奏效?

我已经应用了这些更改。我以前有这样的代码。我最终得到了同样的结果。我猜通过屏幕的是对象的副本,而不是同一个对象。所以执行这些线程使我有两个屏幕副本。所以我需要两个线程来修改相同的屏幕对象。
        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();