Java Concurrent Sockets: not being able to share a variable between threads - java

I happen to have a problem with some attempts at reading the same variable in socket multi-threading, not being able to share it among threads.
It works as an app where an employer assigns work to an employee. Through his interface the employer can add and assignment to an ArrayList inside a class named ListadoPedidos.
When the employer's ServerSocket accepts an employee Socket, it starts a TCP connection and launches the following thread:
public class HiloServer implements Runnable{
private ListadoPedidos peds=new ListadoPedidos();
private ListadoOperarios operarios=new ListadoOperarios();
private ListadoSockets sockets=new ListadoSockets();
private SocketServer s;
public HiloServer(SocketServer sock, JFrame frame, ListadoPedidos pedidos) {
s=sock;
peds=pedidos;
}
/* (non-Javadoc)
* #see java.lang.Runnable#run()
*/
#Override
public void run() {
boolean agregar;
Socket nuevo;
try {
while(true) {
// ACEPTA OPERARIOS QUE DESEEN CONECTARSE
s.aceptar();
nuevo=s.getSocket();
sockets.addSocket(nuevo);
new NuevoCliente();
HiloDatos hd=new HiloDatos(s, nuevo,operarios,peds,sockets);
Thread t=new Thread(hd);
t.start();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
*note that I send the object where the assigments added are stored.
Then it starts another thread that will work as a sort of "validation" for a number the employee's have to insert and send through his Swing interface to truly enter the system. This thread is generated everytime a new socket employee makes a TCP connection to the ServerSocket employer. It goes like:
public class HiloDatos implements Runnable {
private int n;
private Socket cliente;
private SocketServer server;
private int opRecibido;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloDatos(SocketServer ss, Socket nuevo, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
cliente=nuevo;
server=ss;
ops=operarios;
peds=pedidos;
socks=sockets;
}
#Override
public void run() {
server.setSocket(cliente);
boolean agregar, aceptado=false;
try {
do {
// RECIBE EL NRO OPERARIO Y VERIFICA SU EXISTENCIA
agregar=true;
opRecibido=Integer.parseInt(server.recibir());
for(int c=0;c<ops.getOperarios().size();c++) {
if (opRecibido==ops.getOperarios().get(c)) {
new ErrorRepetido();
agregar=false;break;
}
}
if (agregar==true) {
ops.addOperarios(opRecibido);
server.enviar("Si");
aceptado=true;
}
}while(aceptado==false);
HiloPedidos hp=new HiloPedidos(server,opRecibido,ops,peds,socks);
Thread t=new Thread(hp);
t.start();
}catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(cliente));
cliente.close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
And lastly it launches yet another Thread that looks for that same validation number from the thread above in the ArrayList of assignments ("pedidos" of class ListadoPedidos) i kept passing from thread to thread, and if it finds a "new" one, it should send it to the connected socket:
public class HiloPedidos implements Runnable {
private Pedido ped;
private SocketServer server;
private int op;
private ListadoOperarios ops;
private ListadoPedidos peds;
private ListadoSockets socks;
public HiloPedidos(SocketServer ss, int opRecibido, ListadoOperarios operarios, ListadoPedidos pedidos, ListadoSockets sockets) {
server=ss;
opRecibido=op;
ops=operarios;
peds=pedidos;
socks=sockets;
}
#Override
public void run() {
int cambio=0, nuevo;
Pedido pedRecibido;
try {
while(true) {
// ENVÍA PEDIDOS
nuevo=peds.Contar(op);
if(nuevo==cambio) {
cambio=peds.Contar(op);
pedRecibido=peds.TraerNuevo(op, cambio);
server.enviarObjeto(pedRecibido);
}
}}
catch (NumberFormatException e) {
new ErrorDatos();
} catch (ConnectException e) {
new ErrorConexion();
} catch (SocketException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnSocket();
} catch (IOException e) {
try {
socks.getSockets().remove(socks.getSockets().indexOf(server.getSocket()));
server.getSocket().close();
} catch (IOException e1) {
new ErrorFlujo();
}
new WarnFlujo();
}
}
}
Problem is that the last thread can't really notice a change in the list, as i debugged it and never reached the breakpoint inside the condition of sending the assignment. The class ListadoPedidos goes like this:
public class ListadoPedidos {
private static volatile ArrayList<Pedido> pedidos=new ArrayList<>();
public ListadoPedidos() {
}
public ArrayList<Pedido> getPedidos() {
return pedidos;
}
public synchronized void addPedidos(Pedido pedido) {
pedidos.add(pedido);
}
public int Contar(int o) {
int n=0;
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
}
return n;
}
public Pedido TraerNuevo(int o, int c) {
int n=0;
Pedido nuevo = new Pedido();
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
if (n==c) {
nuevo=p;break;
}
}
return nuevo;
}
}
Contar is the one that counts for an assignment with the value nrooperario same as the value it brings from the thread, and TraerNuevo brings the assignment to be sended (never reached this method).
I tried declaring the ArrayList as volatile and all but nothing works. Mind that even if i use socket connections, the problem has more to do with shared varaible not being able to update between threads. Any help will be appreciated.

Try this, basically, synchronize access.
public class ListadoPedidos {
private static volatile ArrayList<Pedido> pedidos=new ArrayList<>();
public ListadoPedidos() {
}
/**
* Here DO NOT return the arrayList. The underlying implementation is not threadsafe
*/
// public ArrayList<Pedido> getPedidos() {
// return pedidos;
// }
public synchronized void addPedidos(Pedido pedido) {
pedidos.add(pedido);
}
public synchronized int Contar(int o) {
int n=0;
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
}
return n;
}
public synchronized Pedido TraerNuevo(int o, int c) {
int n=0;
Pedido nuevo = new Pedido();
for (Pedido p: pedidos) {
if (p.getNro_operario()==o) {
n++;
}
if (n==c) {
nuevo=p;break;
}
}
return nuevo;
}
}

The amount of code you have given us makes it difficult to answer your question. To be honest, the Spanish does not help either. But I can give you some general advice.
Let us start with the question. What exactly is the question? From what I can understand, it comes down to: "how can two threads read the same variable?"
Even if that is not the question, try to make the question as clear as possible for yourself.
Then start with a new test-project separate from the project you are working on. Write the minimal amount of code that you think should work. If it does not work, write even less code that does work (e.g. use static variables to make things even more simple). Go back and forth until you have code that can answer your question. If you cannot get it to work, step back and think about assumptions that you made that might not be true.
If you still cannot figure it out, come back here with the minimal amount of code that you think should work and a clear question.
This method of "trying it with minimal code in a test-project" is something I still use after years of programming to solve problems. When I solve a problem this way, I usually learn something new and often I discover that I made an assumption that did not hold true.

Related

threads synchronization issue

let's say i have 3 classes:
1. Storage which contains just one integer.
2. Counter which contains a thread inside who's responsible for counting (0,1,..,k) and stores each iteration of the loop index in Storage class.
3.Printer which contains a thread who's responsible for reading the value in class Storage and print it.
now i have to create a main class which creates these 3 objects runs the threads of Counter and Printer , and everynumber from(0,1,..,k) has to be printed just once and in the right order.
how do i synchronize the access to my Storage class so first i put a number inside Storage with Counter ,than print it with my Printer class ?
here's what i've wrote so far:
public class Storage {
private int num;
public Storage(){
}
public synchronized void setNum(int num){
this.num = num;
}
public synchronized int getNum(){
return num;
}
public class Counter implements Runnable {
Storage s;
public Counter(Storage t){
s = t;
}
#Override
public void run() {
int i = 0;
while(true){
s.setNum(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Printer implements Runnable {
Storage s;
public Printer(Storage s){
this.s= s;
}
#Override
public void run() {
while(true){
System.out.println(s.getNum());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class mainProg {
public static void main(String[] args){
Storage s = new Storage();
Counter c = new Counter(s);
Printer p = new Printer(s);
Thread c1 = new Thread(c);
Thread p2 = new Thread(p);
c1.start();
p2.start();
}
}
EDIT: i found out a solution, here it is:
public class Storage {
private int num;
private boolean available = false;
public Storage(){
}
public synchronized void setNum(int num){
while(available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = true;
notifyAll();
this.num = num;
}
public synchronized int getNum(){
while(!available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = false;
notifyAll();
return num;
}
}
This approach won't work, because it's not guaranteed that for every cycle of Counter a cycle of Printer will be executed in a parallel thread. You need to be able to store more than a one value in your Storage.
You can use BlockingQueue here and rewrite your Storage class like this:
public class Storage {
private BlockingQueue<Integer> numbers = new LinkedBlockingQueue<Integer>();
public void setNum(int num) {
try {
this.numbers.put(num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int getNum() {
try {
return numbers.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Note that if BlockingQueue is empty and Printer wants to get a new value, it will wait while a new element occurrs in the queue.

Why is my boolean not being changed?

So I'm trying to create a client/server program. I want to know when my client disconnects of his own accord, so I've setup a heartbeat system. Every 6 seconds my client sends a ping to my server, if the client doesn't send a ping for a total of 30 seconds the client is considered disconnected and removed from the current connections list (for which I plan to implement a GUI). Or at least, that's the plan.
ConnectionManager.java
public class ConnectionManager implements Runnable{
static Socket connection;
private ArrayList<Thread> allConnections;
private ArrayList<Connection> allConnectionList;
private ServerSocket server;
private int id = 0;
public ConnectionManager() {
allConnections = new ArrayList<Thread>();
allConnectionList = new ArrayList<Connection>();
}
#Override
public void run() {
try {
server = new ServerSocket(5555);
System.out.println("Server is running!");
while(true) {
connection = server.accept();
Connection a = new Connection(connection, id);
Runnable runnable = a;
allConnectionList.add(a);
allConnections.add(new Thread(runnable));
allConnections.get(allConnections.size() - 1).start();
id++;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void removeConnection(int id) {
allConnections.remove(id);
allConnectionList.remove(id);
}
Connection.java
public class Connection implements Runnable {
private Socket a;
public boolean amIActive;
private int id;
public Connection(Socket a, int id) {
amIActive = true;
this.a = a;
this.id = id;
}
public void onConnect() {
try {
String TimeStamp = new java.util.Date().toString();
String formattedAddress = a.getInetAddress().toString().replace("/", "");
System.out.println("Received connection from: " + formattedAddress + " at " + TimeStamp);
Runnable runnable = new ConnectionListener(this);
Thread connectionThread = new Thread(runnable);
connectionThread.start();
String returnCode = "Server repsonded to " + a.getInetAddress().toString().replace("/", "") + " at "+ TimeStamp + (char) 13;
BufferedOutputStream os = new BufferedOutputStream(a.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
osw.write(returnCode);
osw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
onConnect();
System.out.println("We got this far!");
while(amIActive) {
whileTrue();
}
System.out.println("This code never gets run because we get stuck in the while loop above");
Main.b.removeConnection(id);
System.out.println("Connection was closed from " + a.getInetAddress());
}
public void setOffline(boolean state) {
this.amIActive = state;
}
public void whileTrue() {
}
public Socket getSocket() {
return a;
}
ConnectionListener.java
public class ConnectionListener implements Runnable{
public Connection myConnection;
public boolean receivedHeartbeat;
public int missedHeartbeats = 0;
public ConnectionListener(Connection a) {
this.myConnection = a;
}
#Override
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
while(myConnection.amIActive) {
try {
BufferedInputStream is;
is = new BufferedInputStream(myConnection.getSocket().getInputStream());
InputStreamReader isr = new InputStreamReader(is);
StringBuffer process = new StringBuffer();
int character;
while((character = isr.read()) != 13) { //GETTING STUCK HERE BECAUSE STUPID.
if(character == -1) {
myConnection.setOffline(true);
} else {
process.append((char)character);
}
}
handleInput(process);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void handleInput(StringBuffer process) {
String messageSent = process.toString();
if(messageSent.equals("Ping!")) {
receivedHeartbeat = true;
}
}
Heartbeat.java
public class Heartbeat implements Runnable{
private ConnectionListener b;
public Heartbeat(ConnectionListener a) {
b = a;
}
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
if(b.missedHeartbeats > 5) {
b.myConnection.amIActive = false;
System.out.println("Setting amIActiveToFalse!");
}
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
} else {
b.missedHeartbeats++;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
My console is spammed with System.out.println("Setting amIActiveToFalse!"); from Heartbeat.java. But the while loop in Connection.java keeps running. I believe this might be something to do with my threading, but I can't figure it out.
When you have a non-volatile variable, there is no guarentee of visability of a change in one thread to another. In particular, if the JVM detects that a thread doesn't alter a boolean it can inline it, meaning you will never see the value change.
The simple solution is to make the boolean volatile and it will not be inlined and one thread will see when another changes it.
For more details http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html
The trivial answer to this is: make the variable volatile.
Without this, it is allowed for the thread changing the value to basically keep its updates in cache, committing them to main memory some time later.
This allows threaded code to run much faster, since it can keep its variables in cache rather than having to fetch from main memory. However, the consequence of this is that other threads don't see the update.
Making the variable volatile prevents this from happening: a thread always reads the value from main memory, and writes are immediately committed.
I say that this is the trivial answer because it doesn't necessarily fix all of your problems. There may also be an atomicity issue: in between one thread reading the variable and writing it again, another thread might sneak in and change its value, which may or may not put the first thread into an undefined state from the perspective of its invariants.
Specifically:
if(b.receivedHeartbeat) { b.receivedHeartbeat = false;
It is possible that some other thread can change b.receivedHeartbeat to false after this thread evaluates it to true, so this iteration is erroneously counted as a "non-missed" heartbeat.
This can be fixed by making the variable a (non-volatile) AtomicBoolean, on which there is an atomic compare-and-set method, which avoids such race conditions.
Java Concurrency In Practice is a great reference on these issues, I wholeheartedly recommend it. Look for the topics "visibility" and "atomicity".
Also read the advanced chapter on the Java Memory Model. That made me doubt myself at first, but made me a much stronger programmer after I digested it.
There are a couple issues I saw while debugging the code you posted, but I was able to successfully get the heartbeat functionality working.
In the Connection Listener class I don't think the if statement with .equals("Ping!") will match, because of the newline character at the end of each line.
In the Connection Listener class I would probably put the socket's Input Stream at the top of the loop not inside the loop. (I don't think this will break it but it's probably nicer this way)
ConnectionListener Updates:
public void run() {
Runnable runnable = new Heartbeat(this);
Thread thread = new Thread(runnable);
thread.start();
BufferedReader br = null;
try {
//is = new BufferedInputStream(myConnection.getSocket().getInputStream());
br = new BufferedReader(new InputStreamReader(myConnection.getSocket().getInputStream()));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(myConnection.amIActive) {
try {
String processLine = br.readLine();
System.out.println("handleInput:" + processLine);
handleInput(processLine);
} catch (Exception e) {
System.out.println("Exception!");
e.printStackTrace();
}
}
}
public void handleInput(String messageSent) {
if(messageSent.startsWith("Ping!")) { //Need to use startsWith, or add newline character
receivedHeartbeat = true;
System.out.println("receivedHeartbeat!");
}
}
Also, in your Heartbeat class make sure you reset the missedHeartbeats counter to 0 on true:
if(b.receivedHeartbeat) {
b.receivedHeartbeat = false;
b.missedHeartbeats = 0;
} else {
b.missedHeartbeats++;
}

Java Socket - Updating instance variable List from Thread

I have a simple XO game which have multiple clients play XO Chess with each other. I built a sever which communicate with every clients connected. ( When a client connect to server, i create a new class (implement Runnable) handle that socket then start the Thread ... I have a List store all the client in the outer class ) When a client want to start a game , he make himself a new server and send the info of the Room(his name, IP address, port...) to the Server. And in the server I have a List which add a that room to the list and send it to others Clients.
public class ServerController {
private ServerView view;
private ServerSocket myServer;
private int serverPort = 8881;
private List<ExchangeData> list;
private volatile List<Room> rooms;
public ServerController(ServerView view) {
this.view = view;
openServer(serverPort);
view.showMessage("TCP server is running...");
list = new ArrayList<ExchangeData>();
rooms = new ArrayList<Room>();
while (true) {
listening();
}
}
private void openServer(int portNumber) {
....
}
private void listening() {
try {
Socket clientSocket = myServer.accept();
ExchangeData ex = new ExchangeData(clientSocket);
Thread thread = new Thread(ex);
thread.start();
list.add(ex);
} catch (IOException e) {
System.out.print(e.toString());
}
}
class ExchangeData implements Runnable {
private Socket clientSocket;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private boolean run = true;
public ExchangeData(Socket socket) {
try {
clientSocket = socket;
oos = new ObjectOutputStream(clientSocket.getOutputStream());
ois = new ObjectInputStream(clientSocket.getInputStream());
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
public void closeConnection() {
.....
}
public void sendData(Object o) {
try {
oos.writeObject(o);
} catch (Exception ex) {
view.showMessage(ex.toString());
}
}
public void run() {
try {
while (run) {
Object data = ois.readObject();
if (data instanceof Object[]) {
Object[] o = (Object[]) data;
String s = o[0].toString();
if (s.equalsIgnoreCase("Open Room")) {
Room r = (Room) o[1];
String username = r.getUsername();
InetSocketAddress isa = r.getIsa();
**rooms.add(r);**
List<Room> l = new ArrayList<Room>(rooms);
for (ExchangeData ex : list) {
ex.sendData(username + " Open A room at : "
+ isa);
**ex.sendData(rooms);**
}
} else if (s.equalsIgnoreCase("Close Room")) {
Room room = (Room) o[1];
rooms.remove(room);
List<Room> l = new ArrayList<Room>(rooms);
for (ExchangeData ex : list) {
ex.sendData(l);
}
}
} else if (data instanceof String) {
String s = data.toString();
if (s.equalsIgnoreCase("Quit")) {
stopThread();
list.remove(this);
closeConnection();
}
}
}
} catch (Exception ex) {
try {
stopThread();
list.remove(this);
} catch (ExceptionInInitializerError e) {
e.printStackTrace();
}
}
}
}
}
The problem is when i execute rooms.add(r) , others Thread doesn't seem to see that "update". For example:
1) First player opens a Room - the rooms size is 1;
2) Second player opens a new Room - the rooms size is now 2 ( I tried to add some lines of code in side the method sendData(Object o ) which println the size of rooms and all is 2. But when the line ObjectoutputStream.write(o) is executed, it actually write the value of rooms that Thread(first player) hold before which is 1.
If i create new list like List l = new ArrayList(rooms) like i did with the "Closing Room" then send this , it work. I don't understand why ? Someone please explain this to me. Sorry for my bad English :(.
When you send the same object several time through a given ObjectOutputStream, the stream writes the full object state the first time, but only sends some reference to this object afterwards.
This allows sending complex graphs of objects with cyclic references without consuming too much bandwidth and without going into infinit loops (send A which references B, so send B which references A, so send A which references B, etc.).
So, if you want to send a fresh copy of your list, you'll have to use the reset() method of ObjectOutputStream first.

Unable to store Vector data when calling "call" method in Java

I have a problem with my code. Code is about to find gateways/subnets and if program finds one it returns it to a class that called "call()" method. That part works fine but problem is that I want to pass ID of gateway(you know if gateway was 192.168.1.1 , it will also pass number 1 to class that fills vector of founded gateways). Problem is that for some reason vector that holds IDs of gateways is empty. Can you give me a clue how to fix problem ? Best regards.
Here is code that I used in my project:
int GateWayKey = 1;
int GateWayKeyStop=254;
String ip="";
StoredGW FoundedGW = new StoredGW();
int SubNetKey = 2;
int SubNetKeyStop = 254;
Vector <Integer> AllGateWays= new Vector <Integer>();
Vector <Future<String>> AllSQLs = new Vector <Future<String>>();
final int NUM_THREADS = Runtime.getRuntime().availableProcessors();
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS);
public void run() {
for (;GateWayKey<=GateWayKeyStop;GateWayKey++){
ip="192.168."+GateWayKey+".1";
AllSQLs.add(exec.submit((new PingTask(ip,GateWayKey))));
}
AllGateWays = FoundedGW.GiveMeGWs();
for (int j : AllGateWays){
for (;SubNetKey<=SubNetKeyStop;SubNetKey++){
ip="192.168."+j+"."+SubNetKey;
AllSQLs.add (exec.submit(new PingTask(ip,null))));
}
exec.shutdown();
}
Here is class that preform pinging and storing ID of gateway:
public class PingTask implements Callable <String> {
String ips;
int GateWay;
public PingTask (){
}
public PingTask (String ip, int GateWayKey){
ips=ip;
GateWay=GateWayKey;
}
public String call(){
InetAddress address;
try {
address = InetAddress.getByName(ips);
try {
if (address.isReachable(5000)) {
StoredGW GWs = new StoredGW();
GWs.addNewGW(GateWay);
} else {
return null;
}
} catch (IOException e) {
return null;
}
} catch (UnknownHostException e) {
return null;
}
}
}
and here is class where I store GateWays
public class StoredGW {
Vector <Integer> AllFoundedGWs= new Vector<Integer>();
public void addNewGW(int i){
AllFoundedGWs.add(i);
}
public Vector<Integer> GiveMeGWs(){
return AllFoundedGWs;
}
}
The problem is here:
StoredGW GWs = new StoredGW();
GWs.addNewGW(GateWay);
You make a new StoreGW (as local variable) and then you throw it away. Instead use, FoundedGW. You have to make sure it is visible to your task, you might have to pass it as a constructor argument so that it can be used within your task.
Try this:
public class PingTask implements Callable <String> {
String ips;
int GateWay;
StoredGW store;
public PingTask (){
}
public PingTask (String ip, int GateWayKey, StoredGW store){
ips=ip;
GateWay=GateWayKey;
this.store = store;
}
public String call(){
InetAddress address;
try {
address = InetAddress.getByName(ips);
try {
if (address.isReachable(5000)) {
store.addNewGW(GateWay);
} else {
return null;
}
} catch (IOException e) {
return null;
}
} catch (UnknownHostException e) {
return null;
}
}
}
Then you can call it this way:
AllSQLs.add(exec.submit((new PingTask(ip,GateWayKey, FoundedGW))));
As an unrelated side note, you need to take a look at the standard for Java naming conventions, it'll make your code easier for others to understand.

set and get method not working as planned

I'm simply trying to send a message to another object but its not exactly changing unless I'm missing a important factor. I have one class to set the number and another class which gets, the class that gets is dependent on the correct number being set however although the set method returns 0 one the command line, the other object returns 1 when using the get method. This is the close class whihc holds both of the methods, each method is called from class A and Class B
public class Close {
static int close =1;
public synchronized void setClose(int x, Client)
{
/*
while(turn !=0){
try{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}*/
close = x;
System.out.println("set "+close);
}
public synchronized int getClose(ClientHandeler)
{
int x;
/*
while(turn==0){
try{
wait();
}catch(Exception e)
}
}*/
System.out.println("get "+close);
x = close;
return x;
}
}
This is the handler class in which i wish to get the close integer from
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientHandler implements Runnable {
private BufferedReader reader;
private Socket sock;//refering to socket class
//listens for the socket
private Server server; // call-back reference to transmit message to all clients
Client c = new Client();
public ClientHandler(Socket clientSocket, Server serv) {
try {
sock = clientSocket;
server = serv;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void run() {
String message;
try {
int x = c.c.getClose(this);
while(x!=0){
x = c.c.getClose(this);//calls client and within client there is the close
System.out.println(x);
Thread ct= Thread.currentThread();
ct.sleep(3000);
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
server.tellEveryone(message);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Probably they both do not use the same Close object.
Close close = new Close();
Then make sure that both use the same close object!
If that is not possible, field close can be made static:
public class Close {
static int close;
You could just use an AtomicInteger.
public class Close {
AtomicInteger close = new AtomicInteger(1);
public void setClose(int x)
{
/*
while(turn !=0){
try{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}*/
close.set(x);
System.out.println("set "+close.get());
}
public int getClose()
{
int x;
/*
while(turn==0){
try{
wait();
}catch(Exception e)
}*/
System.out.println("get "+close.get());
x = close.get();
return x;
}
Try...
static int close = 1;
This way there will only be one copy of the int close, for all instances of the Close class. Adding the code where you use this class would help, I'm guessing that you are instantiating new copies for each operation, which is causing your issues.
I don't really understand your problem. May you give a little snippet on how you are using this class?
However, it look very likely that you are not accessing the same instance form your so-called class A and B.
It is just like A is writing something on one paper, and B is reading ANOTHER piece of paper. Of course things written by A is not readable by B.

Categories