在线程运行时更改线程中变量的值

时间:2014-10-29 10:34:41

标签: java android multithreading service tcp

我正在构建一个运行服务的Android应用程序,它有一个侦听tcp连接并接收消息并回复的线程。实际上我想做的是让用户选择回答是或者不,当线程接受连接时,我的服务类是这样的:

public class Receiver extends Service {
    static String TCP_RECEIVE = "soft.b.peopleassist";
    public static String ip;
    DatagramSocket socket;
     private WifiManager.WifiLock wifiLock=null;
     private PowerManager.WakeLock wakeLock=null;
volatile public static String outgoingMsg="null";
    @SuppressLint("DefaultLocale")


    public String getIpAddr() {
           WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
           WifiInfo wifiInfo = wifiManager.getConnectionInfo();
           int ip = wifiInfo.getIpAddress();

           String ipString = String.format(
           "%d.%d.%d.%d",
           (ip & 0xff),
           (ip >> 8 & 0xff),
           (ip >> 16 & 0xff),
           (ip >> 24 & 0xff));

           return ipString;
        }



    private void listenAndWaitAndThrowIntent(Integer port) throws Exception {
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(port);
            //ss.setSoTimeout(10000);
            //accept connections
            Socket s = ss.accept();
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            //receive a message




            String incomingMsg = in.readLine() + System.getProperty("line.separator");
            JSONObject jsonObj = new JSONObject();

            try {
                     jsonObj = new JSONObject(incomingMsg);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                String trans=(String) jsonObj.get("TranId");
                String ide=(String) jsonObj.get("Amount");
                String hashs=(String) jsonObj.get("Basket");
                incomingMsg=trans+","+ide+","+hashs;
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.i("TcpServer", "received: " + incomingMsg);


            //send a message
        //  String outgoingMsg = "goodbye from port " + port + System.getProperty("line.separator");
            // outgoingMsg = "ok"; 

            broadcastIntent(incomingMsg);
            incomingMsg=null;
                Thread.sleep(3000);

            out.write(outgoingMsg);
            out.flush();

            Log.i("TcpServer", "sent: " + outgoingMsg);

            broadcastIntent(incomingMsg);

            //SystemClock.sleep(5000);
            s.close();
            outgoingMsg="null";
        } catch (InterruptedIOException e) {
            //if timeout occurs
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ss != null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }











    private void broadcastIntent(String message) {
    Intent  intent = new Intent(Receiver.TCP_RECEIVE);
        intent.putExtra("messages", message);
        sendBroadcast(intent);
    }

    Thread UDPBroadcastThread;

    void startListenForUDPBroadcast() {
        UDPBroadcastThread = new Thread(new Runnable() {
            public void run() {
                try {
                //  InetAddress broadcastIP = InetAddress.getByName(ip); //172.16.238.42 //192.168.1.255
                    Integer port = 21111;
                    while (shouldRestartSocketListen) {
                        listenAndWaitAndThrowIntent(port);
                    }
                    //if (!shouldListenForUDPBroadcast) throw new ThreadDeath();
                } catch (Exception e) {
                    Log.i("UDP", "no longer listening for UDP broadcasts cause of error " + e.getMessage());
                }
            }
        });
        UDPBroadcastThread.start();
    }

    private Boolean shouldRestartSocketListen=true;

    void stopListen() {
        shouldRestartSocketListen = false;
        if(socket!=null)
        socket.close();
    }

    @Override
    public void onCreate() {
        Log.i("Service", "WiFi lOCK");

        WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
        wifiLock.acquire();

        PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Lock");
        wakeLock.acquire();
    };

    @Override
    public void onDestroy() {
        stopListen();
         wifiLock.release();
            wakeLock.release();

        Log.i("UDP", "Service stoped");
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

            shouldRestartSocketListen = true;

        startListenForUDPBroadcast();
        Log.i("TCP", "Service started");
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

outGoingMsg是实际上是一个响应的消息。现在我希望线程等到线程中这个变量的值没有改变。还有另一个类,我想要改变这个变量。现在我正在调用sleep睡觉这个线程几秒钟,但它不是正确的方式,因为如果几秒后用户没有响应它会自动发送null..please帮助我该怎么做..

1 个答案:

答案 0 :(得分:0)

你可以把等待的动作放到一个循环中,如果设置了值就会中断。 出于可见性的原因,您应该使用挥发性修饰符。

我会在一分钟内发布一个例子。

volatile String valueIAmWaitingFor; // Class Variable
...

while(valueIAmWaitingFor == null){ 
     Thread.sleep(3000); 
}
//go on

另一种方法现在可以设置valueIAmWaitingFor。

volatile:

  

声明一个易变的Java变量意味着:此变量的值   永远不会在线程本地缓存:所有读取和写入都将进行   直接“主记忆”;对变量的访问就像它一样   被包含在同步块中,自身同步。

这只是一种方法。有许多更安全的解决方案(但也比此修补程序更复杂)

编辑:当然必须是valueIAmWaitingFor == null,而不是valueIAmWaitingFor != null