У меня была такая же проблема, как и у вас. Я нашел решение. Короче говоря, вот оно:
Найдите класс Java ScheduledThreadPoolExecutor
, он есть в Java 5 JDK / JRE.
(я могу опубликовать только одну ссылку, как я только что узнал, иначе я бы указал на Oracle JavaDoc)
ScheduledThreadPoolExecutor schedThPoolExec = new ScheduledThreadPoolExecutor(1);
/*
*
* cue a byte buffer for sending in equal segments on the udp port with a inter-pkt-delay
*
*/
public void send(byte[] data, String destinationHost, int destinationPort, double interPacketDelayMs) {
long interDelayNanos = (long) ( interPacketDelayMs * 1000000.0 );
schedThPoolExec.scheduleAtFixedRate( new SendPacketsTimerTask(data, destinationHost, destinationPort), 0, interDelayNanos , TimeUnit.NANOSECONDS);
}
/*
*
*
*
*/
class SendPacketsTimerTask implements Runnable {
int offset = 0;
byte[] buffer;
String host;
int port;
public SendPacketsTimerTask(byte[] buffer, String destinationHost, int destinationPort) {
this.buffer = buffer;
host = destinationHost;
port = destinationPort;
}
@Override
public void run() {
if(offset + PKT_SIZE < buffer.length) {
//copy from cue to packet
byte[] tmp_pkt_buffer = new byte[PKT_SIZE];
System.arraycopy(buffer, offset, tmp_pkt_buffer, 0, PKT_SIZE);
try {
//send packet
socket.send( new DatagramPacket(tmp_pkt_buffer, tmp_pkt_buffer.length, InetAddress.getByName(host), port) );
//increment offset
offset += tmp_pkt_buffer.length;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Наряду с классом TimerTask
(как уже упоминалось выше) вы можете запланировать периодическое проведение мероприятия. Теперь вам просто нужно написать TimerTask, который будет отправлять ваши сообщения, или, как в моем случае, буфер данных.
Моя проблема была на самом деле в том, что я обрабатываю потоки мультимедиа в реальном времени и мне нужна пропускная способность 15 Мбит + (видеоданные). Это приводит к задержке между пакетами в 0,5 мс.
Таким образом, гранулярность метода Thread.sleep
(который принимает аргументы в наносекундах true, но, тем не менее, имеет гранулярность в миллисекундах - также true). Так что я застрял с 6 Мбит скорость передачи. Когда я проверил класс Timer
, я подумал, что нашел свое решение. Окончательно обнаружив, что этот класс не справлялся и с моими низкими периодами исполнения. В поисках людей с похожими проблемами я нашел эту статью
что было очень полезно. Вместо класса Timer
вы можете использовать вышеупомянутый класс планировщика потоков, который, соответственно, привязан к собственному коду, используя полную производительность вашей системы, для периодического запуска метода send с максимально возможным разрешением.
Примечание: общее значение (также у моего работодателя) Java было бы «слишком медленным», «иметь неточные временные характеристики») для выполнения критически важных приложений, и высокая пропускная способность данных в сети, как правило, считается НЕПРАВИЛЬНОЙ. Это было правдой. Наконец, с Java 5 мы можем достичь всех возможных возможностей синхронизации и, следовательно, производительности приложений:)