首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java MultiThreading中面临的问题

java MultiThreading中面临的问题
EN

Stack Overflow用户
提问于 2012-06-25 14:33:59
回答 1查看 240关注 0票数 1

我在多线程期间读取广播数据的流数据捕获中遇到了一个问题,请帮助或建议。

实际上有一个类是从其中一个udp套接字读取数据的。另一个类接受来自每个客户端请求的tcp连接,为每个客户端创建一个线程,并为数据请求相同的udp类。这件事正在与创建的第一个线程一起工作。但是当我从另一个pc/ip向另一个客户端发出请求时,数据包就会丢失到第二个客户端/线程

我已经做了一个变通方法,创建了一个列表来存储对象,并循环将数据发送给所有客户端。但这只是暂时的,因为如果客户端/连接增加,它将延迟数据包。

读取UDP数据的代码

代码语言:javascript
复制
   public class EventNotifier    
    {
      private InterestingEvent ie;
      public DatagramSocket clientSocket;
      public String[] split_str;

      byte[] receiveData;

      HashMap<String, String> secMap = new HashMap<String, String>();


      public EventNotifier(InterestingEvent event)
      {
        ie = event; 
     clientSocket = new DatagramSocket(9050);
        receiveData = new byte[500];
      }



      public String getDataFeed(String client_id)
      {
        try 
        {
             DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
             clientSocket.receive(receivePacket);
             String s = new String(receivePacket.getData());
             String split_str = s.split(","); 
             if(secMap.containsValue(split_str[0]))
                  return s;
             else
                  return "";
             } catch(Exception e3) {}
      }
     }// end of eventNotifier class

多线程处理客户端请求的代码

代码语言:javascript
复制
public class multiServer 
{

    static protected List<PrintWriter> writers = new ArrayList<PrintWriter>();
    static String client_id = "";
    public static void main(String[] args)
    { 
       try
       {
           ServerSocket servsock = new ServerSocket(8858);
           Socket incoming;
           while(true)
           {
             incoming = servsock.accept();
             multiServerThread  connection = new multiServerThread(incoming);

             Thread t1 = new Thread(connection);
             t1.start();
           }
       }
       catch(IOException e)
       {
            System.out.println("couldnt make socket");
       }
    }
}

class multiServerThread extends Thread implements InterestingEvent
{

    Socket incoming;
    PrintWriter out=null;
    PrintWriter broad=null;
    BufferedReader in = null;
    String cliString=null;
    private EventNotifier en; 
    int id;

    public static String udp_data;

    public void interestingEvent(String str1)
    {
          this.udp_data = str1;
    }
    public String getUdpData()
    {
      String _udp_data = this.udp_data;
      return _udp_data;
    }
    multiServerThread(Socket incoming)
    {  
        this.incoming=incoming;
        en = new EventNotifier(this);
    } 
    public void run()
    {
        try
        {
            out = new PrintWriter(incoming.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
        cliString = in.readLine();
        multiServer.writers.add(out);
        while(true)
                {
               try
                   {
                    udp_data = en.getDataFeed(cliString);
                    if(udp_data!=null && udp_data.length()>0)
                    {
              //workaround for serving the data to all cleints who are connected    
                        for (int i=0; i<multiServer.writers.size();i++)
                        {
                            broad=multiServer.writers.get(i);
                            broad.println(udp_data.trim());
                        }
             //else will directly write to the outputstream object for every thread which is connected
             // out.println(udp_data.trim());
                    }

               }
               catch (Exception e)
               {
                 System.out.println("exception "+e);
               }
               Thread.sleep(1);

            }
        } catch(IOException e)
        {
            System.out.print("IO Exception :: "+ e);
        }
        catch(InterruptedException e)
        {
            System.out.print("exception "+ e);
        }        
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-25 16:19:04

您需要互斥(或不同的设计)。

例如,如果两个线程并发调用multiServer.writers.add(out);,会发生什么情况?

从ArrayList Javadoc

请注意,此实现不是同步的。如果多个线程并发访问一个ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部同步该实例。(结构修改是添加或删除一个或多个元素的任何操作,或者...)

另一个问题是两个并发调用udp_data = en.getDataFeed(cliString);。第二个线程可能会覆盖第一个线程的结果。你会丢失数据的!

如果一个线程调用for (int i=0; i<multiServer.writers.size();i++),而另一个线程忙于执行multiServer.writers.add(out);,会发生什么?在out被真正添加到列表之前,大小可能已经增加了!

代码语言:javascript
复制
public class multiServer 
{

    private List<PrintWriter> writers = new ArrayList<PrintWriter>();

    public synchronized void addWriter(PrintWrite out) {
         writers.add(out);
    }
    public synchronized void serveAllWriters(String data) {
         for (int i=0; i<multiServer.writers.size();i++)
         {
             broad=multiServer.writers.get(i);
             broad.println(data);
         }
    }
}

现在,当一个线程试图添加一个写入器时,synchronized将确保没有其他线程正在add或打印。因此,应该修复multiServerThread以使用新方法:

代码语言:javascript
复制
class multiServerThread extends Thread implements InterestingEvent
{
      //...
      private String udp_data;
      //...
      myMultiServer.addWriter(out);

      //...
      udp_data = en.getDataFeed(cliString);
      if(udp_data!=null && udp_data.length()>0)
            myMultiServer.serveAllWriters(udp_data.trim());
      //...
}

可能会有更多的问题,不确定我没有完全理解你的代码。您必须问自己的问题是,另一个线程是否可以读取和/或写入相同的数据或对象?是?那么你将需要适当的同步。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11184427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档