2014-12-03 88 views
0

目前,我试图编写一个程序,它应该多次执行一个独立的Java程序,但使用不同的参数。这个执行的Java程序调用一个线程类。在这个类中,建立到(游戏)服务器的连接。一旦连接,线程将发送一个命令,每10毫秒转换一次连接的播放器。我对这个2的“解决方案”:Java多线程:我如何启动执行线程的外部Java程序?

最简单的(工作)之一:

public class GeneralAgentTest { 

public static void main(String [] args){ 

    Thread thread = new Thread(new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15)); 
    thread.start(); 
} 
} 

这是正常工作,但实际上不是我的目标。我需要启动几个这样的线程(新线程(新的HexagonRunner(“127.0.0.1”,6000,“UnitedTestors”, - 30,-15));),并且每个线程必须由一个独立的进程来处理。

为此,我使用ProcessBuilder编写了一些代码。这是在一个班级内。

二不能正常工作之一:

public void execute(Class class1, int a, String str, String team, String x, 
     String y) { 

    ProcessBuilder builder; 
    String javaHome = System.getProperty("java.home"); 
    String javaBin = javaHome + File.separator + "bin" + File.separator 
      + "java"; 
    String classpath = System.getProperty("java.class.path"); 
    String className = class1.getCanonicalName(); 

    builder = new ProcessBuilder(javaBin, "-cp", classpath, 
      className, ip, port, team, str, x, y); 

    try { 
     process[a] = builder.start(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     System.out.println("failed"); 
    } 

public void loadPlayers() { 
    process = new Process[4]; 
    for (int i = 0; i < 4; i++) { 
     try { 
      execute(processes.StartProcesses.class, i, 
        playerCombo[i].getSelectedItem().toString(), 
        playerTeam[i].getText(), playerStartX[i].getText(), 
        playerStartY[i].getText()); 

     } catch (Exception e) { 
      System.out.println("Failed to create processes for players"); 
      e.printStackTrace(); 
     } 
    } 
} 

这些都是我写的功能,执行谁是/是启动线程(或多个)类(ES)。 下面的类执行:

public class StartProcesses{ 

public static void main(String[] args) { 

     Thread t = null; 
     t = new Thread(new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15)); 
     t.start(); 
      JOptionPane.showMessageDialog(null, "should've started"); 
} 
} 

在我的第二次尝试,这是给予StartProcesses类的参数包含像IP-不会忽略,Portnumbers,Playerpositons和东西像这样的一些信息。无论如何,我试图用“硬”信息来执行这个类,只是为了确保它在我的第一个代码部分中工作。

两次尝试都正确建立了到服务器的连接,但是在第一个连接中线程仍在工作。在我的第二次尝试中,连接建立后线程似乎已经死亡。该过程仍然存在,因为与服务器的连接仍然存在。

这是一段代码,但我想告诉的是,线程在手动执行时正常工作,但如果我尝试使用ProcessBuilder自动启动类,它将无法正常工作。

我真的很希望你们能明白我在说什么。希望有人对我有一个工作解决方案。

干杯。

编辑:添加代码为HexagonRunner:

public class HexagonRunner extends GeneralAgent { 

// Bunch of Methods 
// Important Method: 

    @Override 
protected void simulationCycle() { 

    turnAgent(40); 


} 
} 

的simulationCycle()方法,是将要经过一遍又一遍的方法。 由于类HexagonRunner从类GeneralAgent继承,我要在这里发布这一类的相关的东西,以及:

public class GeneralAgent implements Runnable, UdpListener{ 

// Attributes, getters, setters, methods.. 

@Override 
public final void run() { 
    // giving the worker threads the signal to start 
    mServerConnection.start(); 
    mParser.start(); 

    // waiting for the first information to be parsed, so that the 
    // simulation loop can run 
    try{ 
     System.out.println("GeneralAgent-Run: waiting for latch"); 
     mLogger.info("Run method: waiting for CountDownLatch"); 
     mFirstDone.await(); 
    } 
    catch(InterruptedException e){ 
     System.out.println("GeneralAgent-Run: InterruptedException"); 
     mLogger.info("Run method error: " + e.getMessage()); 
    } 
    mLogger.info("Run method: CountDownLatch now 0, continue"); 
    // setting the initial position 
    moveToPostion(mXStartCoord, mYStartCoord); 

    // the simulation loop 

    while (true){ 
     simulationCycle(); 

     // Shutdown if the game is over 
     if (mGameworld.getTime() >= 6000){ // later 6000+ 
      System.out.println("Yeah, 50 runs completed -> Shutdown"); 
      mLogger.info("General Agent - Time > 50, programm should terminate"); 
      shutdown(); 
      break; 
     } 
     // waiting for the threads to signal that they are 
     // ready (e.g. have new server information) 
     // for another round of the simulation loop 
     mPhaser.arriveAndAwaitAdvance(); 
    } 
} 

我希望事情变得更清晰了。我仍然不知道我的代码在哪里失败。

+0

“但它工作不正常”不是一个适当的问题描述。解释发生了什么,如果有意外发生,或者不应该发生什么;如果有错误消息或异常,请将它们包含在您的问题中。 – Holger 2014-12-03 20:31:46

+0

哦,我忘了这部分。它不能正常工作意味着,线程的机制似乎只执行一次。我在我的HexagonRunner Thread中实现了一个JOptionPane的调用。 JOptionPane只会打开一次,如果我从创建的进程中启动线程。如果我手动执行该线程类的JOptionPane出现requlary。 – 2014-12-03 20:53:13

+0

那么,如果没有看到实际的代码处理这个'JOptionPane',就很难解决这个问题。但作为一般性评论,Swing特性不应该被后台线程访问。参见[“Swing的线程策略”](http://docs.oracle.com/javase/7/docs/api/javax/swing/package-summary.html#threading)。如果你不服从,结果可能是不可预测的。 – Holger 2014-12-04 09:03:38

回答

0

通过使用Executors,您可以更简单地构建一些事情。它是Java 1.5中引入的并发包的一部分。它主要的工作原理如下:

// create a pool with 10 threads 
ExecutorService executorService = Executors.newFixedThreadPool(10); 
//loop as long as you need to detach your threads 
for (int i = 0; i < 4; i++) { 
    // this actually contains the thread bit, will be executed in parallel 
    executorService.execute(new Runnable() { 
     public void run() { 
      // this is where your code is 
      new HexagonRunner("127.0.0.1",6000,"UnitedTestors",-30,-15) 
     } 
    }); 
} 
// clean up when you're done to prevent leaks 
executorService.shutdown(); 

就是这样,多简单,你不需要通过的ProcessBuilder,这是慢了很多产卵不同的JVM。

+0

这看起来不错,但不包含我的主要目标之一。 HexagonRunners必须在单独的进程中运行。这些HexagonRunners实际上是某种具有某种人工智能的足球运动员。服务器的规则之一是,每个玩家必须在其进程中工作。这背后的原因是玩家不能以与服务器功能不同的方式进行通信。 – 2014-12-03 19:12:51

+0

好吧,没关系,你仍然可以在RunBuilder的run()方法中嵌入你的ProcessBuilder。使用执行程序将实际执行命令行调用时产生多个线程的问题分开。 – 2014-12-03 19:18:40

+0

要么我不了解你,要么你不了解我。我试图解释它有点不同。每个HexagonRunner必须与其他人分开开始。这意味着,每个HexagonRunner必须在计算机(JVM)上拥有自己的进程。我不能简单地从一个类中创建一堆这些HexagonRunners。 – 2014-12-03 19:38:03