DataOutputStream采用不同的方法

时间:2013-10-22 15:27:40

标签: java

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

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();


}

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

2 个答案:

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

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

答案 1 :(得分:1)

更好的选择而不是忙于等待一个字段是使用BlockingQueue<String>这将确保你永远不会错过一个值,当你无事可做时也不会消耗CPU。

包装队列和线程(池)的一种好方法是使用同时执行这两种操作的ExecutorService。

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

  

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

创建线程比创建线程多100倍。理想情况下,你不希望有任何一个。注意:Socket已经有写锁定。