2015-12-15 2 views
0

У меня есть приложение, которое общается с UDP-сервером. Мое приложение прослушивает один порт (скажем, 1234) и отправляет по другому (скажем, 5678). Сервер UDP, с которым я общаюсь, также требует «сердцебиения» каждые 5 секунд, для чего я создаю другой поток. Когда мое приложение сначала запускается, я создаю поток прослушивания, затем создаю поток heartbeat, затем я начинаю отправлять пакеты сообщений UDP-сервера. Единственное, однако, состоит в том, что кажется, что все пакеты, которые я отправляю, заканчиваются до начала потока пульса.Почему мои потоки Java не работают одновременно?

Вот что у меня есть для моего слушателя:

public class MyListener implements Runnable { 
    private volatile boolean run = true; 
    private DatagramSocket myDatagramSocket; 
    private DatagramPacket myDatagramPacket; 
    private byte[] receiveBuffer; 
    private int receiveBufferSize; 

    @Override 
    public void run(){ 
     while(run){ 
      try { 
       myDatagramSocket = new DatagramSocket(null); 
       InetSocketAddress myInetSocketAddress = new InetSocketAddress(1234); 
       myDatagramSocket.bind(myInetSocketAddress); 

       receiveBuffer = new byte[2047]; 
       myDatagramPacket = new DatagramPacket(receiveBuffer, 2047); 

       myDatagramSocket.receive(myDatagramPacket); 
       byte[] data = myDatagramPacket.getData(); 

       receiveBufferSize = myDatagramPacket.getLength(); 

       switch(messageID){ 
        ... 
       } 
      } catch (Exception e){ 
      } 
     } 
    } 
} 

Вот что у меня есть для моего сердцебиения:

public class MyHeartbeat implements Runnable { 
    private volatile boolean run = true; 
    private HeartbeatSenderClass heartbeatSender; 

    @Override 
    public void run(){ 
     while(run){ 
      try { 
       TimeUnit.SECONDS.sleep(5); 
       heartbeatSender.sendHeartbeat(); 
      } catch(Exception e){ 
      } 
     } 
    } 
} 

Вот что у меня есть мой основной класс:

public class MyApp { 
    public static void main(String[] args){ 
     MyListener listener = new MyListener(); 
     Thread listenerThread = new Thread(listener); 
     listenerThread.setName("Listener Thread"); 
     listenerThread.start(); 

     MyHeartbeat heartbeat = new MyHeartbeat(); 
     Thread heartbeatThread = new Thread(heartbeat); 
     heartbeatThread.setName("Heartbeat Thread"); 
     heartbeatThread.start(); 

     MySender sender = new MySender(); 
     Thread senderThread = new Thread(sender); 
     senderThread.setName("Sender Thread"); 
     senderThread.start(); 
    } 
} 

Все мои пакеты делают это на UDP-сервере, но не так гладко, как я думал. Я бы подумал, что пока я отправляю пакеты на сервер, каждые 5 секунд мое сердцебиение будет отправлено. Тем не менее, кажется, что мое сердцебиение выходит только после того, как мои пакеты будут отправлены. Кроме того, я считаю, что я не получаю все сообщения с UDP-сервера. Я говорю это, потому что я обнюхал UDP-пакеты на моей машине, и я вижу данные, поступающие с сервера, которые мой получатель не получает/обрабатывает. Какие-либо предложения?

+0

Вы можете поделиться кодом для Отправителя? – idipous

+0

Пустые блоки 'catch' - очень плохая идея, так как вы не сможете узнать, что-то пошло не так. По крайней мере, вызовите 'printStackTrace()' для исключения, которое вы ловите. – VGR

+0

@VGR Они на самом деле не пустые ... Мне просто не хотелось набирать весь этот код в этом посте. – Brian

ответ

0

DatagramSocket, который вы используете для отправки пакетов, является общим ресурсом, который обсуждается между потоками, а затем, если поток потребляет слишком много этого ресурса, другой может голодать. См.: Thread starvation

Также, если вы теряете пакеты, это происходит потому, что вы не можете читать так быстро, как должны. Если пакеты udp поступают быстрее, их можно прочитать, очередь отбрасывает оставшиеся.

Под Linux, например, вы можете контролировать получение буфера с:

sudo sysctl -w net.core.rmem_default=26214400 
sudo sysctl -w net.ipv4.udp_mem='26214400 26214400 26214400' 
sudo sysctl -w net.ipv4.udp_rmem_min=26214400 

Но в любом случае, если мы говорим о устойчивой потере, вы должны рассмотреть, чтобы поток для чтения буфера, очереди и поток для обработки считываемых данных.

+0

Любые предложения для чтения быстрее или это просто предел UDP? – Brian

+0

отредактировал мой ответ с предложением – snovelli

+0

Получил это ... спасибо. – Brian

1

Вы в биении этом:

TimeUnit.SECONDS.sleep(5); 
heartbeatSender.sendHeartbeat(); 

Так что перед отправкой в ​​самый первый удар, вы ждете в течение 5 секунд. Неудивительно, что другие потоки выполняют свою работу тем временем.

+0

Да, но через 5 секунд не следует посылать пульс? Разве это не те потоки? – Brian

+0

Вы пишете выше: «Тем не менее, кажется, что мои сердечные ритмы выходят только после того, как мои пакеты будут отправлены». Мой ответ выше объясняет это. –

+0

Но они находятся в разных потоках. Они должны работать одновременно. Букет пакетов, за которым следует сердцебиение, а затем куча пакетов, сопровождаемое биением сердца и т. Д. – Brian

Смежные вопросы