2014-12-03 89 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