2014-10-20 42 views
1

我的線程越來越混亂。 sendResult()receiveResponse()的結果都應該有不同的響應(我在一個servlet中用JSON響應)。 然而,他們都回復sendResult()的迴應。線程混合起來

有人可以解釋爲什麼這是,以及如何解決這個問題?

class Authenticate { 
    String t2RequestId = null; 
    String finalUserInput = null; 

    public synchronized String sendAuthentication(String deviceId, String requestId, String apiKey) { 
     // Send notification 
     GCM gcmClass = new GCM(); 
     gcmClass.authenticateRequest(deviceId, requestId, apiKey); 

     while(!t2RequestId.equals(requestId)) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     return finalUserInput; 
    } 

    public synchronized void receiveAuthentication(String userInput, String requestId) { 
     finalUserInput = userInput; 
     t2RequestId = requestId; 
     notifyAll(); 
    } 
} 

class T1 implements Runnable { 
    Authenticate m; 
    private final String deviceId; 
    private final String requestId; 
    private final String apiKey; 
    String result; 
    public T1(Authenticate m1, String deviceId, String requestId, String apiKey) { 
     this.m = m1; 
     this.deviceId = deviceId; 
     this.requestId = requestId; 
     this.apiKey = apiKey; 
     Thread t1 = new Thread(this, requestId); 
     t1.start(); 

     // Wait for thread to finish before sending response 
     try { 
      t1.join(); 
     } catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void run() { 
     result = m.sendAuthentication(deviceId, requestId, apiKey); 
    } 
    public String getResult() { 
     return result; 
    } 
} 

class T2 implements Runnable { 
    Authenticate m; 
    private final String requestId; 
    private final String userInput; 
    public T2(Authenticate m2, String requestId, String userInput) { 
     this.m = m2; 
     this.requestId = requestId; 
     this.userInput = userInput; 
     Thread t2 = new Thread(this, "t2" + requestId); 
     t2.start(); 
    } 

    public void run() { 
     m.receiveAuthentication(userInput, requestId); 
    } 
} 
public class AuthenticationHandler { 
    final static Authenticate m = new Authenticate(); 

    public static String sendRequest(String deviceId, String requestId, String apiKey) { 
     T1 runnable = new T1(m, deviceId, requestId, apiKey); 
     String result = runnable.getResult(); 
     return result; 
    } 
    public static void receiveResponse(String requestId, String userInput) { 
     new T2(m, requestId, userInput); 
    } 
} 
+0

有一些我不明白的情況。 T1啓動並且主線程等待T1線程。 但T1線程等待響應,所以T2無法運行。 你在哪裏打電話sendRequest和receiveResponse? – 2014-10-20 20:14:27

+0

你確定你有servlet的迴應嗎? 通知也不是一個好的解決方案,因爲它隨機通知一個線程。例如,你有30個線程在等待,你打電話給一個通知,然後你隨機選擇一個線程 – 2014-10-20 20:15:45

+0

你們的班級舉辦的州可能是一個大問題。 – 2014-10-20 20:30:41

回答

0

我已經找到一個更好的辦法來處理線程的通信,我認爲,有興趣的(?):

全局變量:

TreeMap<String, String> confirmResult = new TreeMap<String, String>(); 

第一線:

Thread.currentThread().setName(requestId); 
    try 
    { 
     synchronized(Thread.currentThread()) 
     { 
      switch(serviceType) 
      { 
       case "GCM": 
        // Send notification to android device 
        GCM gcmClass = new GCM(); 
        gcmClass.authenticateRequest(deviceId, requestId, apiKey); 
        break; 
      } 
      // Wait for reply 
      Thread.currentThread().wait(); 
     } 
     synchronized(this) 
     { 
      if(confirmResult.containsKey(requestId)) 
      { 
       // Get the result 
       String result = confirmResult.get(requestId); 

       // Process the result 
       switch(result) 
       { 
        case "approved": 
         jsonResponse.setResult(0); 
         jsonResponse.setResultText("approved"); 
         break; 
        case "cancelled": 
         jsonResponse.setResult(10000); 
         jsonResponse.setResultText("cancelled"); 
         break; 
       } 
       // Remove the key from the TreeMap 
       confirmResult.remove(requestId); 
      } 
     } 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

第二個線程:

synchronized(this) 
    { 
     // Put the result in the TreeMap 
     confirmResult.put(requestId, confirmation); 
    } 
    // Get a list of all threads 
    Map<Thread, StackTraceElement[]> arr = Thread.getAllStackTraces(); 
    // List the threads 
    for(Map.Entry<Thread, StackTraceElement[]> entry : arr.entrySet()) 
    { 
     // Check if the notify thread still exists 
     if(entry.getKey().getName().equals(requestId)) 
     { 
      synchronized(entry.getKey()) 
      { 
       // Notify the thread 
       entry.getKey().notify(); 
      } 
     } 
    }