面对java MultiThreading中的问题

时间:2012-06-25 06:33:59

标签: java multithreading

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

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

我通过创建一个存储Threads输出流对象的列表来解决方法 并循环它以将数据发送到所有客户端。但这只是暂时的,因为如果客户端/连接增加,它会延迟数据包。

用于读取UDP数据的代码

   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
用于处理客户端请求的多线程的

代码

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

1 个答案:

答案 0 :(得分:0)

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

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

来自ArrayList Javadocs

  

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

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

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

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以使用新方法:

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());
      //...
}

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