次のコードは、/ 24 IP hostListに対する254回のping要求をそれぞれ独自のスレッドで実行します(またはこれは私の考えです)。 full/24サブネット(172.21.0.0/24)がhostListにロードされ、forループ内のワーカーに渡され、各スレッドがキックされてpingが完了します。Javaのicmp4jマルチスレッドpingがマルチスレッドではない
各pingスレッドのタイムアウトは1000msです。したがって、254個のIPが254個のスレッドに渡された場合、完全なプロセスは1〜2秒を超えてはなりません。
つまり、プログラムが本当にマルチスレッドの場合は、2秒未満でこの/ 24インチのすべてのIPにpingできるはずです。
結果は、各ホストが並列ではなく直列にpingされているようです...これを真のマルチスレッドpingアプリケーションにするという点で私は間違っていますか?
/*
* Step 1: Ping a subnet to find alive hosts
*/
package smartsdiscoveryrobot;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.icmp4j.IcmpPingUtil;
import org.icmp4j.IcmpPingRequest;
import org.icmp4j.IcmpPingResponse;
import org.apache.commons.net.util.SubnetUtils; // Subnet Utils to genrate host list
/**
*
* @author beukesmar
*/
public class PingExecutorService {
private static final String COMMUNITY = "public";
private static final int NUMBEROFPINGS = 1;
private static final int PINGTIMEOUT = 1000;
//Determine how many threads should be spawned by fetching the number of processors from Runtime
//private static final int NUM_THREADS = Runtime.getRuntime().availableProcessors();
private static final int NUM_THREADS = 254; //Runtime.getRuntime().availableProcessors();
public static void main(String args[]) throws Exception {
System.out.println("Availabe threads: " + NUM_THREADS);
// Instantitate new Fixed size thread pool with NUM_THREADS
ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
SubnetUtils utils = new SubnetUtils("172.21.0.1", "255.255.255.0");
System.out.println("Low Address: " + utils.getInfo().getLowAddress());
System.out.println("High Address: " + utils.getInfo().getHighAddress());
// Construct hostList with all IP's in above subnet
String[] hostList = utils.getInfo().getAllAddresses();
// Create worker for each host in hostlist
System.out.println("Host array length: " + hostList.length);
for (String host : hostList) {
Runnable worker = new MyRunnable(host, PINGTIMEOUT, COMMUNITY);
executor.execute(worker);
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated()) {
}
System.out.println("\nFinished all threads");
}
public static class MyRunnable implements Runnable {
private final String host;
private final String community;
private final int pingtimeout;
MyRunnable(String host, int pingtimeout, String community) {
this.host = host;
this.pingtimeout = pingtimeout;
this.community = community;
}
@Override
public void run() {
System.out.print("Spawning new thread to ping to host: " + host + " timeout=" + pingtimeout + "\n");
/*
Code to perform ping
*/
final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest();
request.setHost(host);
request.setTimeout(pingtimeout);
request.setPacketSize(32); // Send 32 bytes
// Perform NUMBEROFPINGS pings per host
int numberofpings = NUMBEROFPINGS;
int numberofsuccesspings = 0;
int numberoffailedresponse = 0;
int minlatency = 0;
long avglatency = 0;
int maxlatency = 0;
int sumoflatency = 0;
long totaltime = 0;
boolean isalive = false;
boolean haspacketloss = false;
for (int i = 1; i <= numberofpings; i++) {
final IcmpPingResponse response = IcmpPingUtil.executePingRequest(request);
// host responded to a echo request
if (response.getSuccessFlag() == true) {
isalive = true;
numberofsuccesspings++;
//System.out.println("Reply from " + host + " icmp_req=" + i + " bytes=" + response.getSize() + " time=" + response.getRtt() + "ms");
// Set inital values
if (minlatency == 0) {
minlatency = response.getRtt();
maxlatency = response.getRtt();
}
// Set minlatency if response latency is lower than minlatency
if (response.getRtt() < minlatency) {
minlatency = response.getRtt();
}
// Set maxlatency if response latency is higher than maxlatency
if (response.getRtt() > maxlatency) {
maxlatency = response.getRtt();
}
sumoflatency = sumoflatency + response.getRtt();
totaltime = totaltime + response.getDuration();
// host has dropped a echo request packet
} else {
haspacketloss = true;
numberoffailedresponse++;
//System.out.println("Reply from " + host + ":Error:" + response.getErrorMessage());
totaltime = totaltime + response.getDuration();
}
//final String formattedResponse = IcmpPingUtil.formatResponse(response);
//System.out.println(host + ":" + formattedResponse);
}
long packetloss = numberoffailedresponse/numberofpings * 100;
// Dont devide by 0
if (numberofsuccesspings != 0) {
avglatency = sumoflatency/numberofsuccesspings;
}
/*System.out.println(
"---" + host + " ping statistics ---\n"
+ numberofpings + " packets transmitted, " + numberofsuccesspings + ", " + packetloss + "% packet loss, time " + totaltime + "ms\n"
+ "rtt min/avg/max = " + minlatency + "/" + avglatency + "/" + maxlatency + " ms");*/
System.out.println(host + " isalive=" + isalive + " haspacketloss=" + haspacketloss);
}
}
}
マシンに固定数のコアがあります。その数はおそらく1から16の間のどこかにあります(あなたが "コア"を数える方法に依存します)。おそらく4または8(再び、依存している)。これは、あなたのCPU上で実行できる本当に並行するものの最大数です。これらをインターリーブする場合は、非同期I/Oを実行する必要があります。 –
@ T.J.Crowderは、システムコールでブロックされ、pingへの応答を待っているスレッドは、コアの数をカウントしません。スレッドは、マルチコアCPUよりもずっと長くなっています。人々がそれらを使用し始めた主な理由の1つは、別のスレッドを使用して異なるファイル/デバイス/ネットワークポートで同期I/O呼び出しを行うことが、非同期I/O呼び出しよりも理解しやすくなるからです。 –
@ jameslarge:システムコールの場合はyesです。しかし、非同期I/Oがマルチスレッド同期I/Oより優れた性能を発揮する理由があります。 –