线程混淆了

时间:2014-10-20 20:03:14

标签: java multithreading

我的线程混乱了。 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);
    }
}

1 个答案:

答案 0 :(得分: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();
            }
        }
    }