Create new thread in for loop inside public void method() - java

I have a class that ping IP addresses. To start ping I have public vod run() method to start pinging. Problem is that I want ping more IP addresses at same time (for each IP address I need new Thread). So how can I create new Thread inside for loop. Here is code of my ping class:
public void run()
{
if (dbConnection.ConnectToDB())
{
for (;GateWayKey<=GateWayKeyStop;GateWayKey++)
{
if(stop || this.isInterrupted()){
return;
}
ip="192.168."+GateWayKey+".1";
InetAddress address;
try {
address = InetAddress.getByName(ip);
try {
if (address.isReachable(PingTime))
{
//System.out.println("Pronaden GateWay: "+ip)
// labele.IP
sql="INSERT INTO `iptables` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ip+"', '"+address.getHostName().toString()+"', '"+GateWayKey+"');";
framedocs.WriteMonitorData (ip, address.getHostName().toString(),"2000","DA",dbConnection.WriteToDB(sql));
for (;SubNetKey<=SubNetKeyStop;SubNetKey++)
{
if(stop || this.isInterrupted()){
return;
}
InetAddress addressIps = InetAddress.getByName("192.168."+GateWayKey+"."+SubNetKey);
System.out.println("Provjeravam IP: "+addressIps);
if (addressIps.isReachable(PingTime))
{
ip="192.168."+GateWayKey+"."+SubNetKey;
System.out.println("Pronaden IP: "+ip);
sql="INSERT INTO `iptables` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ip+"', '"+addressIps.getHostName().toString()+"', '"+GateWayKey+"');";
framedocs.WriteMonitorData (ip, address.getHostName().toString(),"2000","DA",dbConnection.WriteToDB(sql));
}
else
{
framedocs.WriteMonitorData (addressIps.toString(), "N/A","2000","NE","N/A");
}
}
}
else
{
framedocs.WriteMonitorData (ip, "N/A","2000","NE","N/A");
}
} catch (IOException e) {
// TODO Auto-generated catch block
framedocs.WriteMonitorData (ip, "N/A","2000",e.getMessage(),"N/A");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
;
framedocs.WriteMonitorData (ip, "N/A","2000",e.getMessage(),"N/A");
}
}
}
else
{
framedocs.WriteMonitorData ("MySQL error", "N/A","N/A","N/A","N/A");
}
}

A general way to do these kinds of tasks is, first, create a class to hold the results you want to get from each thread:
final class PingResult {
public String ip;
public String hostname;
//... other things you want go here
}
Then create a callable that does the actual work
class PingTask extends Callable<PingResult>{
private final String gateWayKey, subNetKey;
//... other parameters you need go here
public Ping( String gwKey, String snKey /*+ others? */ ){
// This is just a way to pass parameters to your pinging function
this.gateWayKey = gwKey;
this.subNetKey = snKey;
// ...
}
public PingResult call(){
// Do actual pinging work here
if ( /* Success */ )
{
PingResult result = new PingResult();
result.ip= /*Fill these in*/;
result.hostname = /* ... */;
return result;
}
// Otherwise we failed, I'm using null as a failure sentinel
// (you can come up with something better)
return null;
}
}
Then in your calling code, set up a thread pool, cue up the requests, and then process the results.
// Might need to tweak the # for best performance
final int NUM_THREADS = Runtime.getRuntime.availableProcesses();
ExecutorService exec = Executors.newFixedThreadPool( NUM_THREADS );
List<Future<PingResult>> results = new ArrayList<PingResult>();
for(/* ... */){
results.add( exec.submit( new PingTask( gateway, subnet ) ) );
}
for( Future<PingResult> future : results ){
PingResult result = future.get();
// Process the result here (this is where you insert into the DB)
}
exec.shutdown(); // VERY IMPORTANT. If you don't do this the JVM will never stop.

create a new class inside your main class and do your operations in that inner class
every-time you need to create a new thread just initiate a new instance of that inner class and call its methods created for this purpose
If you find this answer not useful check my other answer on multi-threading.

Related

Getting socket data on seperate thread and then passing it to main thread

Edited my question for clarification and code:
My goal is to pass my String data from my background thread, to my main application thread. Any help is appreciated.
Here is the code that creates the main background thread. This is located in my Server.java class
public class Server {
boolean isConnected = false;
Controller controller = new Controller();
public void startHost() {
Thread host = new Thread(() -> {
Controller controller = new Controller();
ServerSocket server = null;
try {
server = new ServerSocket(GeneralConstants.applicationPort);
} catch (BindException e2) {
System.out.println("Port Already in Use!");
} catch (IOException e) {
//do nothing
}
while (true) {
if (server == null) { break; }
try {
Socket client = server.accept();
System.out.println("Client Connected: " + isConnected);
if (!isConnected) {
controller.createClientHandler(client);
isConnected = true;
System.out.println("Client Connected: " + isConnected);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
host.setDaemon(true);
host.start();
}
Here is the code that is then called when a client is connected, located in my Controller.java class.
public synchronized void createClientHandler(Socket client) {
boolean alreadyConnected = false;
if (alreadyConnected) {
//do NOT assign multiple threads for each client
} else {
ClientHandler handleClients = new ClientHandler("client", client);
}
}
The program then creates two background threads for my client, one to manage receiving messages, and sending messages.
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(this::receive);
sendThread = new Thread(this::send);
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
The thread then successfully creates the inputstream and passes the object to my controller. Which then process and grabs a string assigning it to a variable
public synchronized void handleReceivedPacket(String name, BufferedReader in) {
try {
data = in.readLine();
System.out.println("Successfully assigned data to: " + data);
} catch (IOException e) {
System.out.println("Unable to read result data");
}
}
How do I access my String data from the main thread without getting null?
Aka I can call (or something similar)
controller.returnData();
from my main application. From which it'll either return null (no data yet), or actually return my data. Right now, it's always null.
Edit, this is what's actually calling controller.returnData() {
I don't want to paste a massive amount of code for fear of reaching StackOverflow's code limit, so here's my application structure.
My JavaFX creates the scene, and creates a root gridpane, it then calls a method that creates sub gridpanes based the specified input. Aka, a user can press "Main Menu" that calls my method setScene() which removes the current "sub-root" gridpane and creates a "new" scene. Right now, I have a GameBoard.java class which on button press, calls controller.returnData()
PassOption.setOnAction(event -> {
System.out.println(controller.returnData());
});
There is no functional purpose for this besides testing. If I can receive the data, then I can expand on this using the data.
Start thinking about design. In network applications you typically have to manage the following responsibilites:
Connected clients and their state (connection state, heartbeats, ...)
Received messages from the clients
Messages to transmit to the clients
It makes sense to separate those responsibilities in order to keep the code clean, readable and maintainable.
Separation can mean both, thread-wise and class-wise.
For example, you could implement it as follows:
The class ClientAcceptor is responsible for opening the socket and accepting clients. As soon as a client has connected, it delegates the further work to a controller and then waits for other clients:
public class ClientAcceptor implements Runnable {
#Override
public void run() {
while (true) {
ServerSocket server;
try {
server = new ServerSocket(1992);
Socket client = server.accept();
if (client.isConnected()) {
controller.createClientHandler(client);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The controller could then create a handler (if the controller decides to do so, e.g. it could also decline the client). The ClientHandler class could look as follows:
public class ClientHandler {
private Thread receiveThread;
private Thread sendThread;
private boolean connected;
private Socket clientSocket;
private String clientName;
private LinkedBlockingDeque<byte[]> sendQueue;
public ClientHandler(String name, Socket s) {
clientSocket = s;
clientName = name;
receiveThread = new Thread(() -> receive());
sendThread = new Thread(() -> send());
connected = clientSocket.isConnected();
receiveThread.start();
sendThread.start();
}
private void receive() {
BufferedInputStream in = null;
try {
in = new BufferedInputStream(clientSocket.getInputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
try {
byte[] bytes = in.readAllBytes();
if (bytes != null && bytes.length > 0) {
controller.handleReceivedPacket(clientName, bytes);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void send() {
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(clientSocket.getOutputStream());
} catch (IOException e) {
connected = false;
}
while (connected) {
byte[] toSend = sendQueue.getFirst();
if (toSend != null && toSend.length > 0) {
try {
out.write(toSend);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void send(byte[] packet) {
sendQueue.add(packet);
}
public void close() {
connected = false;
}
}
The ClientHandler is responsible for receiving and transmitting data. If a packet arrives it informes the controller, which parses the packet. The ClientHandler also provides a public API to send data (which is stored in a queue and handled by a thread) and close the connection.
The above code examples are neither tested, nor complete. Take it as a starting point.

The server is not receiving the message of the client

I'm new to Java socket programming and I'm trying to write a program which is supposed to be run on 2 separate controllers. I have written a thread which is used as the communication class.
I have defined a flag called SFlag so that when the value of this flag is changed to 1 anywhere in my program, the corresponding controller will send a hello message to the other controller through sendPackets() function. The other controller will receive this message through ReceivePackets class and it will print the result. Here is the code:
// My UDP communication class
public class MainConn implements Runnable {
// Sockets, 1 for sending, and one for receiving
DatagramSocket socket1, socket2;
// localIP
private InetAddress localIP;
private InetAddress leaderIP;
// classes to run on separate Threads
private ReceivePackets rcvThread;
#Override
public void run() {
process();
}
public void process() {
// initialize some parameters
init1();
// Make Thread for receiving packets and update counters from all
// controller
rcvThread = new ReceivePackets();
Thread r = new Thread(rcvThread);
r.start();
sendPackets();
}
public void init1() {
try {
// create sockets
String tempString = config.get("localPort");
localPort = Integer.parseInt(tempString);
logger.info("----------here is==========" +localPort);
leaderIP = InetAddress.getByName("127.0.0.1");
logger.info("----------here is==========" +leaderIP);
socket1 = new DatagramSocket(localPort); // for sending
socket2 = new DatagramSocket(localPort + 1); // for receiving
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
}
}
//*******************************************************
public void sendPackets() {
// will be used to begin sending message type II after 3*hello
// period
while (true) {
try {
// if network not converged, send message type I, contains:
// type number (1) then
if (SFlag == 1) {
logger.info("Sending the message");
String tempString = new String("Hello");
byte[] data = tempString.getBytes();
DatagramPacket sentPacket = new DatagramPacket(data, tempString.length());
sentPacket.setAddress(leaderIP);
sentPacket.setPort(20222);
socket1.send(sentPacket);
SFlag = 0;
}
else {
logger.info("Nothinggggggggggggg");
}
Thread.sleep(5000);// wait for Hello period
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
}
}
class ReceivePackets implements Runnable {
#Override
public void run() {
try {
while (true) {
logger.info("---------------waiting------------------");
byte[] data = new byte[1000];
DatagramPacket receivedPacket = new DatagramPacket(data, data.length);
socket2.receive(receivedPacket);
String senderIP = receivedPacket.getAddress().getHostAddress();
String senderPort = "" + receivedPacket.getPort();
String message = new String(data, 0, receivedPacket.getLength());
logger.info(message);
System.out.println("Received Message: "+message);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
When the value of SFlag is changed to 1, it seems that the first controller is sending the message ("Sending the message" is printed), but there seems to be a problem with receiving the message on the second controller, because the received message is not printed.
What is the problem?
There are some issues with your code:
(1) Since both threads rely on SFlag for communication, make sure it is declared with the volatile keyword:
private volatile int SFlag = 0;
The volatile keyword prevents the variable from being cached, so both threads will see the same value all the time. Besides that, reading and writing operations on volatile variables are atomic.
(2) You have a hardcoded port number in this line:
sentPacket.setPort(20222);
Make sure this is the port number used by the ReceivePackets thread. Ideally we should never have magic numbers mixed with the code. So you should move that port number to a separate variable or constant.
(3) In Java you shouldn't create a String with new. For example, this is bad practice:
String tempString = new String("Hello"); // bad practice
You should do:
String tempString = "Hello";
My last piece of advice is: clean up your code. You can look at Oracle's tutorial on sending and receiving datagram packets here: https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html

how to make a callable implementing class multithread fast with parallel execution?

i am creating a class(CheckCon.java) that implements callable interface which basically returns the no. of devices Connected to the network. the problem is that i donot know how to execute it correctly because the results returned are really slow as compared to traditional multithreading. and i need to return values to a class in (NetScan.java). Kindly Help me execute it properly.
code for CheckCon.java (callable implementing class):
public class CheckCon implements Callable<Object>{
int startindex,endindex;
ArrayList<Object> list;
byte[] ip;
public CheckCon(int startindex, int endindex, byte[] ip) {
this.startindex = startindex;
this.endindex = endindex;
this.ip = ip;
list = new ArrayList<>();
}
#Override
public ArrayList<Object> call() throws Exception {
for(int i =startindex;i<endindex;i++){
try {
ip[3] = (byte)i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(1000))
{
System.out.println("Name is......"+address.getHostName()+"\tIP is......."+address.getHostAddress());
}
else if (!address.getHostAddress().equals(address.getHostName()))
{
String host = address.getCanonicalHostName();
String ipaddress =address.toString().replace(host+"/", "");
Object[] data = {host,ipaddress};
list.add(data);
System.out.println("Name is......"+address.getHostName()+"\tIP is......."+address.getHostAddress());
}
else
{
System.out.println("nothing");
// the host address and host name are equal, meaning the host name could not be resolved
} } catch (UnknownHostException ex) {
Logger.getLogger(NetScan.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(NetScan.class.getName()).log(Level.SEVERE, null, ex);
}
}
return list;
}
}
and the class Calling NetScan.java
private void getDataForTable() throws InterruptedException, ExecutionException {
ExecutorService executor =Executors.newCachedThreadPool();
for(int i =0; i<26 ; i++){
if(s == 250){
Future<Object> f =executor.submit(new CheckCon(s,s+5,ip));
list.add(f);
break;
}else{
Future<Object> f =executor.submit(new CheckCon(s,s+10,ip));
list.add(f);
s= s+10;
}
}
dm = new DefaultTableModel(ColumnName,0){
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
for(Future<Object> f : list){
dm.addRow((Object[]) f.get());
}}
I am creating 25 threads checking 10 IP's in each thread.
I removed the CheckCon.java and edited the NetScan to get what i Want thanks to #amit-bera . i Created a thread and asked the completablefuture to runasync with executor defining the no.of threads i require.
ExecutorService e =Executors.newFixedThreadPool(25);
for(int i =0;i<255;i++){
final int j =i;
f = CompletableFuture.runAsync(new Runnable() {
#Override
public void run() {
try {
ip[3] = (byte)j;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(1000))
{
System.out.println("Name is......"+address.getHostName()+"\tIP is......."+address.getHostAddress()+j);
}
else if (!address.getHostAddress().equals(address.getHostName()))
{
String host = address.getCanonicalHostName();
String ipaddress =address.toString().replace(host+"/", "");
Object[] data = {host,ipaddress};
dm.addRow(data);
System.out.println("Name is......"+address.getHostName()+"\tIP is......."+address.getHostAddress()+j);
}
else
{
System.out.println("nothing"+j);
// the host address and host name are equal, meaning the host name could not be resolved
} } catch (UnknownHostException ex) {
Logger.getLogger(NetScan.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(NetScan.class.getName()).log(Level.SEVERE, null, ex);
}
}
},e);
}
added this content to a method.
As per my obervationa please used singolton java pettern.example i am giving below.singolton alwaus retun instance so you save request response time on thread.
Thread is light-wight process but still initilised thread at whenever need.please make sure that thread work based on your server configrationa.
if you are using linux system
used TOP command to usage of your system perfomance and process execution on threadiwse.
i try and its work fine on my system.
class Singleton
{
private static Singleton single_instance = null;
public String s;
private Singleton()
{
s = "Hello I am a string part of Singleton class";
}
public static Singleton getInstance()
{
if (single_instance == null)
single_instance = new Singleton();
return single_instance;
}
}

Program in Jade Running on Netbeans not Transferring Message

I have created an agent which accepts a value and then passes a message on to the next agent. I am having problem with entering a value and so my message is also not being transfered. Here is my Agent class, below. Does anyone know what I can do to fix it?
public class Prgm extends Agent {
int val;
protected void setup() {
Objects[] args = getArguments();
if (args!=null && args.length > 0)
val = Integer.parseInt((String) args[0]);
addBehaviour(new OneShotBehaviour(this) {
public void action() {
if (val == 1) {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.setLanguage("english");
msg.SetOntology("DG Status");
msg.SetContent("DG connected");
msg.addReceiver(new AID("r1", AID.ISLOCALNAME));
myAgent.send(msg);
} else {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(new AID("r1", AID.ISLOCALNAME));
msg.setLanguage("english");
msg.setOntology("DG Status");
msg.setContent("DG not connected");
send(msg);
}
}
});
}
If you don't need to use ontologies right away don't. For strings you can use:
ACLmessage.setContent("string message") and String stringmsg=ACLmessage.getContent()
If you need something more try Java serialization, it's way simpler than using ontologies.
Also I don't think this line is acceptable. new AID("r1", AID.ISLOCALNAME). One would typically contact the df (directory facilitator) agent querying available agents or services. Try something like this
DFAgentDescription template = new DFAgentDescription();
ServiceDescription sd= new ServiceDescription();
sd.setType(Service);
sd.setName(agentName);
template.addServices(sd);
try {
DFAgentDescription[] result = DFService.search(this, template);
listAgents.clear();
for(int i = 0; i<result.length;++i)
{
listAgents.addElement(result[i].getName());
}
//System.out.println(listAgents);
} catch (FIPAException e) {
// TODO Auto-generated catch block
e.printStackTrace();
log(this.getAID() +"!!error in requesting service ="+Service);
}
return (AID) listAgents.get(0);

I want to ensure that my serialevents will not affected by another class

I am writing code that communicates on serially with several machines. Each machine interacts with an instance of a communicator class and that class has a serial port event listener.
When the machine recieves enough data it peforms a test that is quadratic. (cant be helped as the test itself is quadratic) and the input can be large. As a result I am afraid that some of the serial events wont be registered if the code is doing the calculation.
As a solution I considered creating a Thread that runs the calculation and setting it to sleep during its loop for a time determined by the number of machines connected. However I then thought that maybe it would be a better idea if I could put that Thread asleep from the serialevent method? is this possible or will the thread not run until the method that is running finishes?
Now in the code below I have included the Thread.sleep within the Calculations method as this is what I was going to do if the serialevent cant interupt the thread
private class CalculationThread implements Runnable{
#Override
public void run()
{
calculateResult();
}
}}
private void calculateResult() {
ArrayList<Double> theoretical_vals;
ArrayList<ArrayList<Double>> theoretical_curves = new ArrayList();
double current_maxdiff, maxdiff;
double ao = measurements.get(0).getMeasurement();
theoretical_vals = RadioCalculations.theoreticalVals(measurements, hf, ao);
theoretical_curves.add(theoretical_vals);
int index = 1;
for (MeasurePoint m : measurements) {
theoretical_vals = RadioCalculations.calibratecontrolValues(measurements, index, hf);
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));}
catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
theoretical_curves.add(theoretical_vals);
index++;
}
index = 1;
maxdiff = 0;
for (ArrayList a : theoretical_curves) {
try {
Thread.sleep(20*(parent.getNumberOfTests()-1));
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
current_maxdiff = compareValues(a, measurements);
if (current_maxdiff > maxdiff) {
if (current_maxdiff > pass_limit) {
passed = false;
failed_measurementpoint = index;
break;
}
maxdiff = current_maxdiff;
index++;
}
}
passed = true;
max_dev = maxdiff;
logResults();
}
public void serialEvent(SerialPortEvent spe) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
pauseListen(false);
if (spe.getEventType()== SerialPortEvent.DATA_AVAILABLE){
try {
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);}}
catch (IOException e) {e.printStackTrace();}
input_line= new String(readBuffer,0,numBytes);
input_line = input_line.replaceAll("[\n\r]","*");
buffer.append(input_line);
if (input_line.contains("*")){
input_line= buffer.toString();
input_line = input_line.replaceAll("[*]","");
buffer.setLength(0);
pauseListen(true);
update(input_line);}}
}
}
You could use a BlockingQueue (since Java 5) for put the new calculations in this queue while there is one calculation in process.
First, you need a wrapper class for you received data of the serial port:
class CalculationWrapper {
// fields
// getters setters
public void calculateResult() {
// operations
}
}
The method calculateResult for do the calculations can be in this class or in the next class:
class Calculator implements Runnable {
private final BlockingQueue<CalculationWrapper> queue;
Calculator(BlockingQueue<CalculationWrapper> q) {
queue = q;
}
public void run() {
try {
while (true) {
CalculationWrapper wrapper = queue.take();
wrapper.calculateResult();
}
} catch (InterruptedException ex) {
// log error
}
}
}
The method take wait until there is more new calculations in the queue.
The class for the listener of events of serial port (and for put the new calculations) could be:
class Receiver implements Runnable, SerialPortEventListener {
private final BlockingQueue<CalculationWrapper> queue;
Receiver(BlockingQueue q) {
queue = q;
}
public void run() {
try {
while (true) {
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
// log
}
}
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
try {
// read
CalculationWrapper wrapper = new CalculationWrapper();
// set data on wrapper
queue.put(wrapper);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
And the setup class o main class:
class Setup {
public static void main(String args[]) {
// get port
// register listener
BlockingQueue q = new ArrayBlockingQueue(10);
Receiver p = new Receiver(q);
Calculator c1 = new Calculator(q);
new Thread(p).start();
new Thread(c1).start();
}
}
This in one way. See more:
Lesson: Concurrency (The Java Tutorials > Essential Classes)
SerialPort example « javax.comm « Java by API
The Java Communications API: A Working Example - By Rick Proctor

Categories

Resources