0

我在应用程序中使用此代码发送一些字符串,抛出一个套接字。

public class OutgoingData {

public static DataOutputStream dos = null;
public static String toSend = "";
public static volatile boolean continuousSending = true;
public static String toSendTemp = "";

public static void startSending(final DataOutputStream d) {

    new Thread(new Runnable() {

        public void run() {
            try {
                dos = d;
                while (continuousSending) {

                    if (!toSend.equals(toSendTemp)) {
                        dos.writeUTF(toSend);
                        dos.flush();
                        toSendTemp = toSend;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }).start();

}

从另一个线程我调用这个方法

    private void send(String str) {

    OutgoingData.toSend = str;
}

使用此实现是否会出现任何问题?从两个线程同步调用 send() 的情况除外。

我没有使用这样的东西:

   private void send(final String str){

    new Thread(new Runnable() {

        @Override
        public void run() {
            synchronized (OutgoingData.dos) {
                try {
                    OutgoingData.dos.writeUTF(str);
                    OutgoingData.dos.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }).start();


}

因为运行此代码的系统对进程可以创建的线程数有限制,并且需要很长时间才能锁定对象。

4

2 回答 2

1

您的实现不是线程安全的:

if (!toSend.equals(toSendTemp)) {
    // toSend can be changed before this line happens
    // causing you to miss data
    dos.writeUTF(toSend);
    dos.flush();

    // or here
    toSendTemp = toSend;
}

您需要某种形式的线程同步,无论它是否“慢”。

于 2013-10-22T15:40:52.220 回答
1

比忙于等待字段更好的选择是使用 aBlockingQueue<String>这将确保您永远不会错过任何值,也不会在无事可做时消耗 CPU。

包装队列和线程(池)的一个好方法是使用两者都做的 ExecutorService。

在您的情况下, Socket 流已经是一个队列,因此排队写入另一个队列可能是多余的,您真正需要缓冲输出流。

因为运行此代码的系统对进程可以创建的线程数有限制,并且需要很长时间才能锁定对象。

创建线程比创建线程要多 100 倍。理想情况下,您也不想拥有。注意:Socket 已经有写锁。

于 2013-10-22T16:02:01.470 回答