IN serial communication some time data miss at receive time and some time its miss and send time at receiver side . I observe that data send and receive successfully when I am set baud rate is 300800 please check following code ===>
receiver==>
I am using Jserial com for communication
also open port port and set baud rate, partity=1, NumDataBits=8,NumStopBits=1
comPort.addDataListener(new SerialPortDataListener() {
#Override
public int getListeningEvents() {
{
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
// return 0;
}
#Override
public void serialEvent(SerialPortEvent serialPortEvent) {
if (serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
logger.info("in HLIToModbusConversionController" + "event_type="
+ serialPortEvent.getEventType());
return;
}else {
logger.info("in HLIToModbusConversionController getCommandFromSerial() getEventType:" + serialPortEvent.getEventType());
}
ExecutorService executorService = null;
try {
//50 ml time out
executorService = Executors.newSingleThreadExecutor();
long sTime = System.currentTimeMillis();
int len = serialPortEvent.getSerialPort().bytesAvailable();
byte dataBuffer[] = new byte[len];
serialPortEvent.getSerialPort().readBytes(dataBuffer, len);
for (int i = 0; i < dataBuffer.length; i++) {
byte b = dataBuffer[i];
logger.info("in HLIToModbusConversionController" + String.format("%02x ", b));
}
logger.info("in HLIToModbusConversionController" + dataBuffer);
Future<byte[]> future = executorService
.submit(new TimeOutTask(hliToModbusService, dataBuffer));
while (!future.isDone()) {
long totalTime = System.currentTimeMillis() - sTime;
if (totalTime > configurationModel.getModbusTimeout()) {
logger.info("Task is taking long time to execute so cancelling it..");
future.cancel(true);
}
}
byte responseFrame[] =null;
//byte responseFrame[] = hliToModbusService.decodeHLICommand(dataBuffer); // service
try {
responseFrame = future.get((long) configurationModel.getModbusTimeoutSecond(), TimeUnit.SECONDS);
logger.info("result:"+responseFrame);
fileOperationUtil.writeFramFromCache(responseFrame);
} catch (Exception e) {
logger.info("50 millisecond time out frame takes from cache");
responseFrame =fileOperationUtil.readFramFromCache();
} // call
modbusRequest.setTimeout(false);
if (responseFrame != null) {
comPort.writeBytes(responseFrame, responseFrame.length);
logger.info("in HLIToModbusConversionController response frame sent" + responseFrame);
// wait for 100ms
} else {
logger.info(
"in HLIToModbusConversionController responseFrame is empty" + responseFrame);
}
String finalFrame="";
for(byte data:responseFrame) {
finalFrame=finalFrame+","+data;
}
logger.info(
"in HLIToModbusConversionController final responseFrame:" + finalFrame);
startTimer();
logger.info("in HLIToModbusConversionController returns from startTimer");
} catch (Exception e) {
logger.info("in HLIToModbusConversionController exception occurs");
e.printStackTrace();
}finally{
if(executorService != null){
executorService.shutdown();
}
}}
});
}
}
//comPort = SerialPort.getCommPorts()[0]; // take 1st port
} catch (Exception e) {
logger.info("in HLIToModbusConversionController exception occurs");
e.printStackTrace();
}
logger.info("in HLIToModbusConversionController");
logger.info("Server started");
logger.info("Waiting for a client ...");
return "Hli server started";
Related
I have a simple rmi-server and rmi-client. When i run this server and client in same network, my server function returns the result properly. But my server and client are in different networks and if the process time is more than 3-4 minutes client can not get the result, although server fihishes the operation.
here is my entire server code:
public class SimpleServer {
ServerRemoteObject mRemoteObject;
public static int RMIInPort = 27550;
public static int delay = 0;
public byte[] handleEvent(byte[] mMessage) throws Exception {
String request = new String(mMessage, "UTF-8");
// if ("hearthbeat".equalsIgnoreCase(request)) {
// System.out.println("returning for hearthbeat");
// return "hearthbeat response".getBytes("UTF-8");
// }
System.out.println(request);
Thread.sleep(delay);
System.out.println("returning response");
return "this is response".getBytes("UTF-8");
}
public void bindYourself(int rmiport) {
try {
mRemoteObject = new ServerRemoteObject(this);
java.rmi.registry.Registry iRegistry = LocateRegistry.getRegistry(rmiport);
iRegistry.rebind("Server", mRemoteObject);
} catch (Exception e) {
e.printStackTrace();
mRemoteObject = null;
}
}
public static void main(String[] server) {
int rmiport = Integer.parseInt(server[0]);
RMIInPort = Integer.parseInt(server[1]);
delay = Integer.parseInt(server[2]);
System.out.println("server java:" + System.getProperty("java.version"));
System.out.println("server started on:" + rmiport + "/" + RMIInPort);
System.out.println("server delay on:" + delay);
SimpleServer iServer = new SimpleServer();
iServer.bindYourself(rmiport);
while (true) {
try {
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and here is my client code:
public class SimpleClient {
ISimpleServer iServer;
public SimpleClient(String p_strServerIp, String p_strCMName, int nRMIPort) {
try {
if (nRMIPort == 1099) {
iServer = (ISimpleServer) Naming.lookup("rmi://" + p_strServerIp + "/" + p_strCMName);
} else {
Registry rmiRegistry = null;
rmiRegistry = LocateRegistry.getRegistry(p_strServerIp, nRMIPort);
iServer = (ISimpleServer) rmiRegistry.lookup(p_strCMName);
}
} catch (Exception ex) {
ex.printStackTrace();
iServer = null;
}
}
public static void main(String... strings) {
String ip = strings[0];
int rmiport = Integer.parseInt(strings[1]);
System.out.println("client java:" + System.getProperty("java.version"));
System.out.println("client is looking for:" + ip + ":" + rmiport);
SimpleClient iClient = new SimpleClient(ip, "Server", rmiport);
try {
byte[] response = iClient.iServer.doaction("this is request".getBytes("UTF-8"));
System.out.println(new String(response, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
and here is my rmi-registry code:
public class SimpleRMI implements Runnable {
Registry mRegistry = null;
public SimpleRMI(int nPort) {
try {
mRegistry = new sun.rmi.registry.RegistryImpl(nPort);
} catch (RemoteException e1) {
e1.printStackTrace();
}
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(360000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String... strings) {
int rmiport = Integer.parseInt(strings[0]);
System.out.println("rmi java:" + System.getProperty("java.version"));
System.out.println("rmi started on:" + rmiport);
SimpleRMI iRegisry = new SimpleRMI(rmiport);
Thread tThread = new Thread(iRegisry);
tThread.start();
byte[] bytes = new byte[1];
while (true) {
try {
System.in.read(bytes);
if (bytes[0] == 13) {
try {
iRegisry.listRegistry();
} catch (Exception exc2) {
exc2.printStackTrace();
}
}
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
private void listRegistry() {
String[] strList = null;
try {
strList = mRegistry.list();
if (strList != null) {
for (int i = 0; i < strList.length; i++) {
int j = i + 1;
String name = strList[i];
java.rmi.Remote r = mRegistry.lookup(name);
System.out.println(j + ". " + strList[i] + " -> "
+ r.toString());
}
}
System.out.println();
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
and my remote interface and remote object:
public interface ISimpleServer extends java.rmi.Remote {
public byte[] doaction(byte[] message) throws java.rmi.RemoteException;
}
#SuppressWarnings("serial")
public class ServerRemoteObject extends UnicastRemoteObject implements ISimpleServer {
SimpleServer Server = null;
public ServerRemoteObject(SimpleServer pServer) throws RemoteException {
super(SimpleServer.RMIInPort);
Server = pServer;
}
#Override
public byte[] doaction(byte[] message) throws RemoteException {
try {
return Server.handleEvent(message);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
when i run client and server in different networks. (i run client in my home network) and if delay is more than 3-4 mins server prints returning response but client still waits for the response. If delay is only 1 minute, clients gets the result properly.
Can you please help me to find where the problem is?
I am trying to give a pop up alert message when my ThreadpoolExecutor is finished executing. It is searching email addresses from websites, once it is done I want a alert message as "Completed". Here is my Thread :-
public class Constant
{
public static final int NUM_OF_THREAD = 60;
public static final int TIME_OUT = 10000;
}
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool
(Constant.NUM_OF_THREAD);
Here is my Searching Operation class :-
class SearchingOperation implements Runnable {
URL urldata;
int i;
Set<String> emailAddresses;
int level;
SearchingOperation(URL urldata, int i, Set<String> emailAddresses, int level) {
this.urldata = urldata;
this.i = i;
this.emailAddresses = emailAddresses;
this.level = level;
if (level != 1)
model.setValueAt(urldata.getProtocol() + "://" + urldata.getHost() + "/contacts", i, 3);
}
public void run() {
BufferedReader bufferreader1 = null;
InputStreamReader emailReader = null;
System.out.println(this.i + ":" + poolMainExecutor.getActiveCount() + ":" + level + ";" + urldata.toString());
try {
if (level < 1) {
String httpPatternString = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9#:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9#:%_\\+.~#?&//=]*)";
String httpString = "";
BufferedReader bufferreaderHTTP = null;
InputStreamReader httpReader = null;
try {
httpReader = new InputStreamReader(urldata.openStream());
bufferreaderHTTP = new BufferedReader(httpReader
);
StringBuilder rawhttp = new StringBuilder();
while ((httpString = bufferreaderHTTP.readLine()) != null) {
rawhttp.append(httpString);
}
if (rawhttp.toString().isEmpty()) {
return;
}
List<String> urls = getURL(rawhttp.toString());
for (String url : urls) {
String fullUrl = getMatchRegex(url, httpPatternString);
if (fullUrl.isEmpty()) {
if (!url.startsWith("/")) {
url = "/" + url;
}
String address = urldata.getProtocol() + "://" + urldata.getHost() + url;
fullUrl = getMatchRegex(address, httpPatternString);
}
if (!addressWorked.contains(fullUrl) && fullUrl.contains(urldata.getHost())) {
addressWorked.add(fullUrl);
sendToSearch(fullUrl);
}
}
} catch (Exception e) {
//System.out.println("652" + e.getMessage());
//e.printStackTrace();
return;
} finally {
try {
if (httpReader != null)
bufferreaderHTTP.close();
} catch (Exception e) {
// e.printStackTrace();
}
try {
if (httpReader != null)
httpReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
String someString = "";
emailReader = new InputStreamReader(urldata.openStream());
bufferreader1 = new BufferedReader(
emailReader);
StringBuilder emailRaw = new StringBuilder();
while ((someString = bufferreader1.readLine()) != null) {
if (someString.contains("#")) {
emailRaw.append(someString).append(";");
}
}
//Set<String> emailAddresses = new HashSet<String>();
String emailAddress;
//Pattern pattern = Pattern
//.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Pattern
pattern = Pattern
.compile("\\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z0-9.-]+\\b");
Matcher matchs = pattern.matcher(emailRaw);
while (matchs.find()) {
emailAddress = (emailRaw.substring(matchs.start(),
matchs.end()));
// //System.out.println(emailAddress);
if (!emailAddresses.contains(emailAddress)) {
emailAddresses.add(emailAddress);
// //System.out.println(emailAddress);
if (!foundItem.get(i)) {
table.setValueAt("Found", i, 4);
foundItem.set(i, true);
}
String emails = !emailAddresses.isEmpty() ? emailAddresses.toString() : "";
model.setValueAt(emails, i, 2);
model.setValueAt("", i, 3);
}
}
} catch (Exception e) {
//System.out.println("687" + e.getMessage());
} finally {
try {
if (bufferreader1 != null)
bufferreader1.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (emailReader != null)
emailReader.close();
} catch (Exception e) {
e.printStackTrace();
}
Thread.currentThread().interrupt();
return;
}
}
After this the final snippet :-
private void sendToSearch(String address) throws Throwable {
SearchingOperation operation = new SearchingOperation(new URL(address), i,
emailAddresses, level + 1);
//operation.run();
try {
final Future handler = poolMainExecutor.submit(operation);
try {
handler.get(Constant.TIME_OUT, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
handler.cancel(false);
}
} catch (Exception e) {
//System.out.println("Time out for:" + address);
} catch (Error error) {
//System.out.println("Time out for:" + address);
} finally {
}
}
Implement Callable<Void> instead of Runnable and wait for all the task to terminate by calling Future<Void>.get():
class SearchingOperation implements Callable<Void>
{
public Void call() throws Exception
{
//same code as in run()
}
}
//submit and wait until the task complete
Future<Void> future = poolMainExecutor.submit(new SearchingOperation()).get();
Use ThreadPoolExecutor.awaitTermination():
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
As in your code, you create your ThreadPoolExecutor first
ThreadPoolExecutor poolMainExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Constant.NUM_OF_THREAD);
Then, you need to add Tasks to it:
poolMainExecutor.execute(myTask);
poolMainExecutor.submit(myTask);
execute will return nothing, while submit will return a Future object. Tasks must implement Runnable or Callable. An object of SearchingOperation is a task for example. The thread pool will execute the tasks in parallel, but each task will be executed by one thread. That means to effectively use NUM_OF_THREAD Threads you need to add at least NUM_OF_THREAD Tasks.
(Optional) Once you got all jobs to work, shutdown your pool. This will prevent new tasks from being submitted. It won't affect running tasks.
poolMainExecutor.shutdown();
At the end, you need to wait for all Tasks to complete. The easiest way is by calling
poolMainExecutor.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
You should adjust the amount of time you want to wait for the tasks to finish before throwing an exception.
Now that the work is done, notify the user. A simple way is to call one of the Dialog presets from JOptionPane, like:
JOptionPane.showMessageDialog(null, "message", "title", JOptionPane.INFORMATION_MESSAGE);
It will popup a little window with title "title", the message "message", an "information" icon and a button to close it.
This code can be used., it will check whether the execution is completed in every 2.5 seconds.
do {
System.out.println("In Progress");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (poolMainExecutor.getActiveCount() != 0);
System.out.println("Completed");
I have a list of threads that need to be executed simultaneously. I was doing this using executorservice initially. The threads that need to be executed are coming from DB and I am retrieving their classnames, storing them in vendorDetails list.
for (Object vendorThread : vendorDetails) {
String thread = (String) vendorThread;
//timeout = details.getTimeout();
Runnable worker = null;
try {
Class c = Class.forName(thread);
Constructor<?> cons = c.getConstructor(SearchRequest.class, Results.class);
worker = (Runnable) cons.newInstance(searchRequest, Results);
} catch (Exception e) {
//e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
executor.execute(worker);
}
executor.shutdownNow();
try {
if (!executor.isTerminated()) {
executor.awaitTermination(timeout, TimeUnit.SECONDS);
}
} catch (InterruptedException ex) {
//ex.fillInStackTrace();
}
I want to achieve something similar in ejb so I am using ManagedExecutorService.
#EJB
private ThreadName1 threadName1 ;
#EJB
private ThreadName2 threadName2 ;
for (Object vendorThread : vendorDetails) {
System.out.println("in for loop");
String thread = (String) vendorThread;
System.out.println("thread:" + thread);
//timeout = details.getTimeout();
Runnable worker = null;
try {
if (thread.equals("threadName1")) {
System.out.println("in if");
threadName1.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName1;
} else if (thread.equals("threadName2")) {
System.out.println("in spice if");
threadName2.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName2;
}
System.out.println("after if");
} catch (Exception e) {
e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
System.out.println("before execute");
//managedExecutorService.execute(worker);
managedExecutorService.submit(worker);
System.out.println("after execute");
}
System.out.println("before shutdown");
//managedExecutorService.shutdownNow();
System.out.println("after shutdown");
try {
System.out.println("after shutdown");
/*if (!managedExecutorService.isTerminated()) {
managedExecutorService.awaitTermination(timeout, TimeUnit.SECONDS);
}*/
} catch (InterruptedException ex) {
ex.fillInStackTrace();
// ex.printStackTrace();
}
So ideally I want the threads to run for a stipulated time say 30secs and then return the results of whichever threads have completed their execution.
Now the problem is calling any threadlifecycle methods like shutdown etc throws an exception.
How do I achieve this?
I am using the default ManagedExecutorSerivce.
I dont know if this is the right solution. But I am doing this for now as a workaround. Adding to a Future list all the tasks that are submitted. Then waiting for stipulated time and cancelling all the running tasks. I am sure there is a more elegant solution.
ArrayList<Future> taskList = new ArrayList<>();
for (Object vendorThread : vendorDetails) {
System.out.println("in for loop");
String thread = (String) vendorThread;
System.out.println("thread:" + thread);
//timeout = details.getTimeout();
Runnable worker = null;
try {
if (thread.equals("threadName1")) {
System.out.println("in if");
threadName1.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName1;
} else if (thread.equals("threadName2")) {
System.out.println("in spice if");
threadName2.setReqRes(SearchRequest, Results);
worker = (Runnable) threadName2;
}
System.out.println("after if");
} catch (Exception e) {
e.printStackTrace();
}
if (worker == null) {
System.out.println("------------------------ WORKER IS NULL ---------------");
}
System.out.println("before execute");
//managedExecutorService.execute(worker);
taskList.add(managedExecutorService.submit(worker));;
System.out.println("after execute");
}
System.out.println("before shutdown");
//managedExecutorService.shutdownNow();
System.out.println("after shutdown");
try {
System.out.println("after shutdown");
/*if (!managedExecutorService.isTerminated()) {
managedExecutorService.awaitTermination(timeout, TimeUnit.SECONDS);
}*/
System.out.println("before sleep");
long startTimeLogon = System.currentTimeMillis();
boolean allComplete;
int trueCount = 0;
while (true) {
System.out.println("true count " + trueCount++);
if ((System.currentTimeMillis() - startTimeLogon) >= timeout * 1000) {
break;
}
allComplete = true;
for (Future f : taskList) {
if (!f.isDone()) {
allComplete=false;
}
}
if(allComplete)
break;
Thread.sleep(250);
}
System.out.println("after sleep");
for (Future f : taskList) {
if (!f.isDone()) {
f.cancel(true);
}
}
System.out.println("after cancel");
} catch (InterruptedException ex) {
ex.fillInStackTrace();
// ex.printStackTrace();
}
I'm trying to put working a simple servlet (copied from another source). It's an async servlet that reads a post request using NIO through a ReadListener. This is the code:
#WebServlet(name = "AsyncProxyServlet2", urlPatterns = "/*" , asyncSupported = true)
public class AsyncProxyServlet2 extends HttpServlet
{
private static final long serialVersionUID = 8458401860448619054L;
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
final AsyncContext acontext = request.startAsync();
final ServletInputStream input = request.getInputStream();
System.out.println("request.isAsyncStarted() = " + request.isAsyncStarted() + ", request.isAsyncSupported = " + request.isAsyncSupported() + ", main = " + Thread.currentThread().getName());
input.setReadListener(new ReadListener()
{
byte tmp[] = new byte[4*1024];
ByteArrayOutputStream buffer = new ByteArrayOutputStream(this.tmp.length);
#Override
public void onDataAvailable()
{
try
{
System.out.println("onDataAvailable = " + Thread.currentThread().getName());
int numBytesRead = -1;
while ( input.isReady() && !input.isFinished() )
{
if ( (numBytesRead = input.read(this.tmp)) > 0 ) this.buffer.write(this.tmp, 0, numBytesRead);
}
}
catch (IOException ex) { ex.printStackTrace(); }
}
#Override
public void onAllDataRead()
{
try
{
System.out.println("onAllDataRead = " + Thread.currentThread().getName() + ", buffer size = " + this.buffer.size());
acontext.getResponse().setContentType("text/xml; charset=utf-8");
acontext.getResponse().setContentLength(this.buffer.size());
acontext.getResponse().getOutputStream().write(this.buffer.toByteArray());
}
catch (Exception ex) { ex.printStackTrace(); }
acontext.complete();
}
#Override
public void onError(Throwable t) { t.printStackTrace(); }
});
System.out.println("final 1");
try { Thread.sleep(3000); } catch (Exception e) {}
System.out.println("final 2");
}
}
When I send a post request to this servlet, the output of this code is:
request.isAsyncStarted() = true, request.isAsyncSupported = true, main = http-nio-80-exec-1
final 1
<-- Here a 3 second pause
final 2
onDataAvailable = http-nio-80-exec-1
onAllDataRead = http-nio-80-exec-1, buffer size = 910
So it seems that everything is executed on the same thread. The request is not read until the 3-second pause ends, then the last 3 messages are printed.
Why is this not working properly?
There is a 3 seconds pause...
try { Thread.sleep(3000); } catch (Exception e) {}
Just comment out this line.
I'm trying to print out in order my Log statements instead of randomly after each ping? Should I use wait and notify from object class to allow each thread to finish? Not sure how to go about this.
Main class
public class Main
{
public static void main(String[] args)
throws InterruptedException, ExecutionException, IOException
{
Scan4SMB scan4Servers = new Scan4SMB();
List<String> networkNames = scan4Servers.doScan();
for (String networkName : networkNames)
{
LOG.CONSOLE.debug(networkName);
}
}
}
Scan class
public class Scan4SMB
{
private final int THREADS = 256;
private final int SMB_PORT = 445;
private List<String> smbNames = new ArrayList<String>();
private List<String> foundDevicesArray = new CopyOnWriteArrayList<String>();
private byte[] ip;
Scan4Servers() throws UnknownHostException
{
// this code assumes IPv4 is used
ip = Inet4Address.getLocalHost().getAddress();
LOG.CONSOLE.debug("LocalHost ip: " + ip);
}
Scan4Servers(Inet4Address address) throws UnknownHostException
{
ip = address.getAddress();
LOG.CONSOLE.debug("LocalHost IP: " + ip);
}
protected List<String> doScan() throws IOException
{
LOG.CONSOLE.debug("Start scanning");
ExecutorService executor = Executors.newFixedThreadPool(THREADS);
for (int i = 1; i <= 254; i++)
{
ip[3] = (byte) i;
InetAddress address = null;
try
{
address = InetAddress.getByAddress(ip);
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
executor.execute(pingRunnable(address));
}
LOG.CONSOLE.debug("Waiting for executor to terminate...");
executor.shutdown();
try
{
executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
}
catch (InterruptedException ignored)
{
}
LOG.CONSOLE.debug("Scan finished");
return smbNames;
}
private Runnable pingRunnable(final InetAddress address) {
return new Runnable() {
public void run() {
LOG.CONSOLE.debug("Pinging " + address + "...");
try {
Socket socket = new Socket(address, SMB_PORT);
LOG.CONSOLE.debug("Connection: " + socket.toString());
if (socket.isConnected()) {
LOG.CONSOLE.debug("connected " + address.toString());
String ipString = address.toString().substring(1,
address.toString().length());
NbtAddress[] addr = NbtAddress
.getAllByAddress(ipString);
String NETNAME = addr[0].firstCalledName();
// String NETNAME1 =
// addr[0].nextCalledName();
smbNames.add(NETNAME);
LOG.CONSOLE.debug("NETNAME " + NETNAME);
LOG.CONSOLE.debug("addr " + addr);
foundDevicesArray.add(address.toString());
LOG.CONSOLE.debug("hostname added to found "
+ address.toString());
socket.close();
}
socket.close();
} catch (UnknownHostException e) {
// LOG.CONSOLE.debug("Not found", e);
} catch (IOException e) {
// LOG.CONSOLE.debug("IO Error", e);
}
}
};
}
protected List<String> getList()
{
return smbNames;
}
}
There are many ways to do it. Here's one possible approach using a CountDownLatch -- a simple but versatile way to coordinate threads. I modified your pingRunnable to accept 2 latches. It will wait for the first latch before before printing any output. It will clear the second latch after it's done.
This way every Runnable will wait for the previous one to be done before printing anything. The scanning will still occur in parallel but the output will be synchronized.
Here's the modified loop in doScan method:
CountDownLatch lastLatch = new CountDownLatch(0);
for (int i = 1; i <= 254; i++) {
ip[3] = (byte) i;
InetAddress address = null;
try {
address = InetAddress.getByAddress(ip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
CountDownLatch nextLatch = new CountDownLatch(1);
executor.execute(pingRunnable(address, lastLatch, nextLatch));
lastLatch = nextLatch;
}
And Here's the modified pingRunnable:
private Runnable pingRunnable(final InetAddress address, CountDownLatch waitFor, CountDownLatch clearWhenDone) {
return new Runnable() {
public void run() {
try {
Socket socket = new Socket(address, SMB_PORT);
waitFor.await(); // wait for all previous runners to log their output
LOG.CONSOLE.debug("Connection: " + socket.toString());
if (socket.isConnected()) {
LOG.CONSOLE.debug("connected " + address.toString());
String ipString = address.toString().substring(1,
address.toString().length());
NbtAddress[] addr = NbtAddress
.getAllByAddress(ipString);
String NETNAME = addr[0].firstCalledName();
// String NETNAME1 =
// addr[0].nextCalledName();
smbNames.add(NETNAME);
LOG.CONSOLE.debug("NETNAME " + NETNAME);
LOG.CONSOLE.debug("addr " + addr);
foundDevicesArray.add(address.toString());
LOG.CONSOLE.debug("hostname added to found "
+ address.toString());
socket.close();
}
socket.close();
} catch (UnknownHostException e) {
// LOG.CONSOLE.debug("Not found", e);
} catch (IOException e) {
// LOG.CONSOLE.debug("IO Error", e);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
} finally {
clearWhenDone.countDown(); // signal to the next Runnable that we are done
}
}
};
}
My understanding is that you want to run a bunch of tasks in parallel, (the ping), but you want the log messages to print in the order the tasks were submitted to the executor, but only after they are done.
We can do that.
// I'm taking some liberty with your code, so the concepts are highlighted
ExecutorService exec = ....;
// Important thing is to have a list of result futures
List<Future<String>> results = new ArrayList<>();
// we have some way to generate our work. For loop like above is fine.
List<String> addresses = imagineWeHaveAListOfAddresses();
for( String address : addresses ) {
// here we record the future returned by the ExecutorService
results.add(exec.submit(pingRunnable(address), address);
}
// result.get() is blocking, so we'll print the addresses in the same order we submitted them.
for( Future<String> result : results ) {
LOG.info("Finished address: " + result.get());
}
I hope that helps.