2015-10-09 2 views
0

Я следующий сценарий:Java как ждать завершения команды?

Connection con = new Connection("host",80); 

    ByteBuffer loginbb = ByteBuffer.allocate(300); 
    <snip> 
    loginbb.flip(); 

    byte[]login = new byte[loginbb.remaining()]; 
    loginbb.get(login); 


    ByteBuffer headerbb = ByteBuffer.allocate(7); 
    <snip> 
    headerbb.flip(); 

    byte[]header = new byte[headerbb.remaining()]; 
    headerbb.get(header); 

    con.run(login, header); 


    try { 
     Thread.sleep(1000); 
    } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } 


    long pid = Long.parseLong(request.getParameter("player")); 
    PrintWriter out = response.getWriter(); 
    ByteBuffer bb = ByteBuffer.allocate(100); 
    bb.putLong(pid); 
    bb.putLong(pid); 
    bb.put((byte) 0x00); 
    bb.flip(); 

    byte[] payload = new byte[bb.remaining()]; 
    bb.get(payload); 


    ByteBuffer headerbb2 = ByteBuffer.allocate(7); 
    <snip> 
    headerbb2.flip(); 

    byte[]header2 = new byte[headerbb2.remaining()]; 
    headerbb2.get(header2); 

    con.send(payload, header2); 

    try { 
     Thread.sleep(700); 
    } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } 

    Gson gson = new GsonBuilder().setPrettyPrinting().create(); 
    JsonParser jp = new JsonParser(); 
    JsonElement je = jp.parse(Avatar.getJson().toString()); 
    String json = gson.toJson(je); 
    out.flush(); 
    out.println(json); 
    out.flush(); 

Обратите внимание на следующее?

try { 
     Thread.sleep(700); 
    } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } 

и это:

try { 
     Thread.sleep(1000); 
    } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
    } 

Так что задержавшись мой сценарий на некоторое время, но я не хочу, это так, как сценарий может занять больше или меньше времени. Это было бы пустой тратой времени D:

Что я хочу, так это то, что он просто ждет завершения работы.

con.run в основном выполняет начальную задачу, а затем - con.send.

con.send в основном работает следующим образом:

private void sendToServer(byte[] message, int length, byte[]header) { 

    byte[]payload = outrc4.encrypt(message,false); 
    byte[] data = new byte[header.length+payload.length]; 

    System.arraycopy(header,0,data,0,header.length); 
    System.arraycopy(payload,0,data,header.length,payload.length); 


    try { 
     out.write(data); 
    } catch (IOException e) { 
     System.out.println("Error!"); 
    } 
} 

Он просто посылает пакет на сервер.

Отсюда, на con.run, я получаю несколько пакетов обратно. Я могу поймать идентификатор пакета и в цикле, который получает и анализирует пакет, я могу добавить оператор if, который проверяет, принят ли пакет loginDone.

void receive() { 
    try { 

     while (in.available() > -1) { 

       int type = in.readUnsignedShort(); 
       int size = in.readUnsignedByte(); 
       size <<= 8; 
       size |= in.readUnsignedByte(); 
       size <<= 8; 
       size |= in.readUnsignedByte(); 
       int version = in.readUnsignedShort(); 

       byte array[] = new byte[7]; 
       array[0] = (byte)((type >>> 8) & 0xFF); 
       array[1] = (byte)(type & 0xFF); 
       array[2] = (byte)((size >>> 16) & 0xFF); 
       array[3] = (byte)((size >>> 8) & 0xFF); 
       array[4] = (byte)(size & 0xFF); 
       array[5] = (byte)((version >>> 8) & 0xFF); 
       array[6] = (byte)(version & 0xFF); 

       final byte[] reply = new byte[size]; 

      in.readFully(reply,0,size); 

      byte[] data = new byte[array.length + reply.length]; 
      System.arraycopy(array, 0, data, 0, array.length); 
      System.arraycopy(reply, 0, data, array.length, reply.length); 
      byte[] decryptedPayload = inrc4.encrypt(reply,false); 

      if(type == 20000){ 
       updateKeys(decryptedPayload); 
      } 

      if(type == 24411){ 
      //this one means that the 1st packet that uses con.run is done 

       System.out.println("Logged In!"); 
      } 

      if(type == 24334){ 
      //this one means that the 2nd packet that uses con.send is done 

       InputStream myis = new ByteArrayInputStream(decryptedPayload); 
       new Avatar(myis); 
       t.interrupt(); 
      } 

     } 


    } catch (Exception e) {} 

} 

Возьмите не из этих комментариев: // это один означает, что второй пакет, который использует con.send делается и // это один означает, что первый пакет, который использует con.run делается

Это все, что у меня есть. Кто-нибудь имеет представление о том, что я должен делать здесь?

+0

Это слишком много кода для просеивания, но я думаю, что вы ищете wait() notify() https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html – WalterM

ответ

1

Если ваш сервер и клиент находятся в одном и том же Java-качестве, используйте для этого CountDownLatch или thread.join(). Если они разные машины, прочитайте часть EDIT.

class Foo extends Thread { 

    CountDownLatch latch; 

    public Foo(CountDownLatch latch) { 
     this.latch = latch; 
    } 
    @Override 
    public synchronized void start() { 

     try { 
      sleep(1000); 
      latch.countDown(); // in every call latch decrease one, when it reach to zero, every thread that is waiting the latch will continue. 
sleep(100); 
     } catch (InterruptedException e) { 

     } 
    } 
}  
class FooBar { 

    public static void main(String[] args) throws InterruptedException { 

     CountDownLatch latch = new CountDownLatch(1); 

     new Foo(latch).start(); 

     latch.await(); // wait latch reach to zero. BE CAREFUL, IT'S NOT WAIT(), 
         // IT'S AWAIT() 
     System.out.println("done"); 
    } 
} 

EDIT Я буду держать код, указанный выше в целях простоты. Я думаю, что это очень самоочевидно, может помочь другим.

Хорошо, если вы хотите подождать до метод полностью, вам нужно разработать способ, которым сервер может сказать клиенту, что этот метод завершен, или вы можете разработать способ, которым ваш клиент будет проверять какое-либо состояние на сервере, например isTaskCompleted(). Я не знаю, насколько сложна ваша ситуация, чтобы сервер отправил пакет клиенту. Я опишу в основном два подхода к этой ситуации, я буду использовать другое имя класса и переменных, поэтому попробуйте адаптироваться к вашему коду.

public class WaitServer extends Thread { 

    synchronized void serverCompleted() { 
     // when server completes 
     notify(); 

    } 

    @Override 
    public synchronized void start() { 

     try { 
      wait(); // waits the server 
     } catch (InterruptedException e) {      

     }  
    } 
} 
class ClientSide { 

    void doSomething() { 

     // ... some stuff ....  
     sendToServer(); 

     new WaitServer().join(); 

     // continues execution  
    } 
} 

class ServerSide { 
    void received() { 

     // ... do some stuff ..... 

     if (someStuff) {    
      sendSignalToClient(); 

     }  
     // .. others stuff   
    } 

    void sendSignalToClient() {  
     // here of course you need to send in the way that you are sending today, this is "pseudocode" 
     client.serverCompleted()   
    }  
} 

Другой подход, чтобы сделать проверку клиент-сервер, пока задача не будет завершена, просто создать Протяните отправить подтверждение задания, если не завершен сон в течение некоторого времени. Если вы хотите сделать поток, чтобы ждать другого использования join(). Если вы хотите, чтобы поток ожидал некоторую часть обработки внутри другой, используйте CountDownLatch.

+0

объясните пожалуйста :) –

+0

@ShivamPaw вы хотите подождать, пока получите() будет завершено или только до отправки()? –

+0

Посмотрите, поможет ли это: http://stackoverflow.com/questions/15956231/what-does-this-thread-join-code-mean –