I am writing a content distribution network in java. I have a Link class to manage sockets between two nodes in the system. There are two programs, RouterNode and DiscoveryNode.
When a router node starts up, the first thing it does is try to initialize a connection to the discovery node:
public RouterNode(int num)
{
myNumber = num;
input = new Scanner(System.in);
try {
discoveryServer = new Socket("MONDAY-PC", 60111);
myServerLink = new Link(this, discoveryServer);
} catch (IOException e) {
System.out.println("Socket could not be opened. Node terminating.");
System.exit(-1);
}
There is more to the constructor, but my problem keeps my program from getting past this try block.
The constructor of the link class (called on the line 'myServerLink = new Link(this, discoveryServer); ) looks as such:
public Link(Node n, Socket s)
{
parentNode = n;
regSocket = s;
try {
out = new DataOutputStream(regSocket.getOutputStream());
in = new DataInputStream(regSocket.getInputStream());
} catch (IOException e) {
System.out.println("Data Streams could not be created on the link.");
e.printStackTrace();
}
new Thread(new LinkListenerThread(this, in)).run();
}
where the last line of this constructor starts a new thread that is designed to listen on the socket for incoming messages that are being passed.
The run() method in LinkListenerThread stars as follows:
#Override
public void run()
{
byte[] message;
System.out.println("Link now active and running.");
while(!done)
{
System.out.println("attempting to read from socket...");
try {
// read now many bytes the following message will be
byte[] messageLengthBytes = new byte[4];
in.read(messageLengthBytes, 0, 4);
My problem is that once I instantiate the link from the router node, it's execution stops from what seems to be the LinkListenerThread blocking it when it calls in.read(). This listener is running on a separate thread so I am not sure if this is actually something strange with threads, or it is just an example of my lack of experience with them.
I have another instance in my program where I am reading on a separate thread
Could this be caused because the node classes aren't explicitly implementing runnable and therefore are not on their own threads?
Any help is greatly appreciated.
Edit 1: I have made the Node classes implement Runnable and starting them on their own threads, but it still locks up when the in.read() is called;
You intend to start a thread by calling Thread.run() method instead of Thread.start(). And this makes your program single-threaded, then the I/O ops block the only thread(the main thread) in the try-catch clause if there is no data coming in or the while loop never ends.
Just use Thread.start() to start a thread can fix your problem.
The problem has been resolved by using .start() instead of .run()
It all boiled down to a misunderstanding of how to instantiate threads in java.
Related
I'm using scanner to read lines from file and replace some text in each line based on given pattern. This is done inside an API. My program is a multithreaded one. At once, more than one thread can call this particular API.
Following is the line scanner initialization line where the thread crashes:
public static void replaceInFile(Properties replacements, Path targetFile) {
...
Scanner in = new Scanner(targetFile, "UTF-8");
...
}
I'm sure no single file will be accessed by two threads at once. Can anyone hint me in the right direction as to what is happening?
UPDATE:
public Void call() throws Exception {
Iterator it = paths.iterator();
while(it.hasNext()){
try {
String filePath = it.next().toString();
//BuildUtil replacer = new BuildUtil();
BuildUtil.replaceInFile(replacements, Paths.get(filePath));
} catch(Exception e) {
e.printStackTrace();
}
}
This is the call() of the thread. Now I observe that it shows "Frame not available" even before stepping into the BuildUtils's replaceInFile method and sometimes after entering in there..I'm not able to figure out what's wrong.. The main thread is exiting I think but I see nothing strange happening here which should make it exit unexpectedly.
I found it. Actually it was my stupidity. I forgot to wait for the threads to exit and so the main thread exited even before threads could complete. Sorry for bothering!
So now I do :
for (int i = 0; i < threadsUsed; i++) {
pool.take().get();
}
for all the threads and shutdown the executor service in finally block
I am building a server that sends data via a single TCP socket for each user every 2 seconds and on a separate thread. There are also special events occasionally sent along side with the regular data. Sometimes, data in multiple packets would mix up so I created a queue to make sure it does not happen. However, the issue is still there, is my approach not correct or is there something wrong with my code?
protected void sendData (byte[] data) {
if (isSendingData) {
dataQueue.add(data);
return;
}
isSendingData = true;
Thread sendThread = new Thread() {
public void run () {
try {
BufferedOutputStream outStream = new BufferedOutputStream(connectionSocket.getOutputStream());
outStream.write(data);
outStream.flush();
// check queue, if there are data, send
byte[] moreData = null;
if (dataQueue.size() > 0) {
moreData = dataQueue.remove(0);
}
isSendingData = false;
if (moreData != null) {
sendData(moreData);
}
}
catch (Exception e) {
System.out.println ("Error sending data to peripheral: " + e);
isSendingData = false;
}
}
};
sendThread.start ();
}
The proper idiom to remove concurrency issues using a queue is to have a long-lived thread run an infinite loop which takes elements from the queue and processes them. Typically you'll use a blocking queue so that on each iteration the thread goes to sleep until there is an item to process.
Your solution deviates from the above in many aspects. For example:
if (isSendingData) {
dataQueue.add(data);
return;
}
isSendingData = true;
—if this method is called concurrently, this will result in a race condition: both threads can read isSendingData as false, then concurrently proceed to sending data over the network. If isSendingData isn't volatile, you've also got a data race on it (entirely separate from the race condition explained above).
if (dataQueue.size() > 0) {
moreData = dataQueue.remove(0);
}
—this is another race condition: after you read size as zero, the other thread can add an item to the queue. Now that item will possibly never be processed. It will linger in the queue until another such thread is started.
The more obvious way your solution is not correct is that the thread you start has no loops and is intended to just process one message, plus possibly one extra message in the queue. This should be reworked so that there are no special cases and sendData always, unconditionally, submits to a queue and never does any sending on its own.
I would do this completely differently. You don't want arbitrarily long queues in your application.
Have your hearbeat thread synchronize on the socket when sending the heartbeat.
Don't have it sending anything else.
Get rid of the queue, isSendingData, etc.
Have your main application synchronize on the socket when it wants to send, and just send whenever it needs to.
Use the same BufferedOutputStream or BufferedWriter for all sending, and flush it after each send.
I'm in the process of writing some tests to drive development for a side project of mine, and am encountering some very strange Java behavior:
Object.wait() causes the main thread of execution to return and skip all of the following lines of execution, but only the second time it's called in a loop.
The reason I know this is because I'm attempting to write tests without the use of Thread.sleep() because I believe it is generally bad practice to insert these in main threads of execution, especially tests which would later scale and become extremely long-running tasks.
Here is my test:
#Test
public void testSendReceiveAll() throws Exception {
for (String s : (ArrayList<String>)testFiles) {
((FakeSendFileApi) sendFileApi).setSender(new InetSocketAddress(LOCALHOST,
LOCALPORT)).setIncomingFileName(s + incrAppend());
PendingFile pendingFile = new PendingFile(TEST_PATH + s, new InetSocketAddress(LOCALHOST,
LOCALPORT));
SendAction sendAction = new SendAction(pendingFile);
Thread sendActionThread = new Thread(sendAction);
synchronized (sendAction){
sendActionThread.start();
sendAction.wait(TIMEOUT_MS);
}
File file = new File(s + fileAppend);
assertTrue(file.exists());
assertTrue(file.isFile());
assertTrue(file.canRead());
assertTrue(file.delete());
}
}
Explanation of what it does: Iterate over all of the test files and send and receive them all locally. There is a SendAction class which is instantiated and run in the test:
/**
* Attempts to send the specified file to the specified <code>InetSocketAddress</code>.
* The file's path must be specified completely either absolutely or relatively.
*
* #return true if <code>pendingFile</code> was sent successfully in its entirety.
*/
public synchronized void run() {
try {
ServerSocket serverSocket = new ServerSocket(pendingFile.getSender().getPort());
serverSocket.setSoTimeout(socketTimeoutMillis);
// Blocks until a connection is made on specified socket or until TIMEOUT is reached.
Socket socket = serverSocket.accept();
System.out.println("Sending file " + pendingFile.getFileName());
OutputStream outputStream = socket.getOutputStream();
sendByteArray(new RandomAccessFile(pendingFile.getFileName(), "r"), outputStream);
serverSocket.close();
notifyAll();
} catch (IOException e) {
System.err.println(e); // TODO log error appropriately
}
}
The problem: When I hit the synchronized block of the test, and start the thread to send, then wait for a notify from that sendAction, this works the first time in the loop. The second time through however, the test simply passes and exits on the call to
sendAction.wait(TIMEOUT_MS);
This only occurs sometimes, and not others. I have put print statements to see if I can achieve the race condition without debugging and it does send and receive the first file, but doesn't always send and receive the second file. When I put a println() statement just after the sendAction.wait(TIMEOUT_MS); call, it never executes after the second loop iteration.
What gives???
waits should always occur in loops. (Refer to javadoc of Object.wait() for more details).
Maintain a flag to mark the completion of the task and use it in the condition to guard sendAction.wait()
while(!sendAction.finished) {
sendAction.wait(TIMEOUT_MS);
}
set "sendAction.finished" to true before calling the notifyAll()... AND DO THIS IN FINALLY.
I'm working on a Java Project using Sockets. Since the Socket Methods are Blocking Methods, I'm forced to make a multithreaded application.
As of now, I am able to read the incoming bytes from an other application. I write them into a StringBuilder. My problem is how to return this string back to my main thread. I was thinking of something like an Event, which I can call as soon as the Socket-Thread has finished reading.
I am happy for any ideas.
public class SocketRunnable implements Runnable {
private final Socket _socket;
public SocketRunnable(Socket socket){
this._socket = socket;
}
#Override
public void run() {
StringBuilder sb = new StringBuilder();
try {
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
this._socket.getInputStream()));
char[] buffer = new char[100];
int amountOfBytes = bufferedReader.read(buffer, 0, 100); // blocks until the message is received.
String message = new String(buffer, 0, amountOfBytes);
sb.append(message);
} catch (IOException ex) {
Logger.getLogger(SocketRunnable.class.getName()).log(Level.SEVERE, null, ex);
}
finally{
// Return (!)
}
}
My problem is how to return this string back to my main thread.
You can't—not due to any technical obstacles, but because it doesn't make conceptual sense. Your main thread has already gone on its way and the context where your return value made sense is lost.
So, either:
your main thread must block to receive the result (but what's the point of multithreading then);
your main thread is already designed from the ground up in an event-oriented fashion and has an outer event loop which takes events off of a queue and handles them (this is true if you are building a GUI application).
What makes more sense is to make the result available to some other code. It can all happen in the same thread, the one which did the receiving. You can achieve this by simply calling an appropriate method. So, the thing to solve in your design is, how to make an instance which has that method available to the code which is executed in the reading thread.
You can use the Callable interface in conjunction with Executors.
You can read about it here:
Callable:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html
Executors:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
Just implement the callable interface with your SocketRunnable class (there is one method - call(), which will return the value from one thread to another thread upon completion).
To display the result into a Swing TextField you can process the result, once you have the string just do:
final String msg=???; // Insert your string here
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textBox.setText(msg);
}
});
The invokeLater call will put you onto the correct thread to modify the contents of the text field.
Write the result String in a blocking queue, and let the main thread poll or take from that queue.
I am trying to create a java socket program with multithread concept.
Every single connection from client to the server is a thread.
Every client send their information to server.
I want to ask how to collect all value from the threads and put them all in an array of string?
Is needed to synchronized all this threads?
What the different if use only Thread t = new Thread() instead of Thread[] t = new Thread(client)?
Am i right for the beginning step with use Thread[] to collect all item from the threads?
Is it useful to use thread join()?
This is part which create thread,
public void listenSocket(int client){
int i=0;
Thread[] t = new Thread[client];
while(i<client){
ClientWorker w;
try{
w = new ClientWorker(server.accept());
t[i] = new Thread(w);
t[i].start();
System.out.println(t[i].getName());
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
i++;
}
}
This is the part of what the thread doing
class ClientWorker implements Runnable{
Socket client;
String ip;
String load;
String data[]=new String[7];
ClientWorker(Socket client){
this.client = client;
}
public void setIP(String ip){
this.ip = ip;
}
public void setData(String load){
this.load = load;
}
public void getIP(){
System.out.println(ip);
}
public void getData(){
System.out.println(load);
}
public void run(){
BufferedReader in = null;
PrintWriter out = null;
XmlGenerator xml = new XmlGenerator();
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("in or out failed");
}
while(true){
try{
String a = in.readLine();
setData(a);
String b = client.getRemoteSocketAddress().toString();
setIP(b);
out.println(a);
getData();
getIP();
}
catch (IOException e) {
System.out.println("Read failed");
}
}
}
}`
i've read the topic about sync,callable thread but i found nothing.
sorry for repost.
There are two ways to answer this:
First way:
I want to ask how to collect all value from the threads and put them all in an array of string? Is needed to synchronized all this threads?
If you are going to collect the results that way, then yes it is necessary to explicitly synchronize the threads' use of that array.
What the different if use only Thread t = new Thread() instead of Thread[] t = new Thread(client)?
It is not clear what you mean, but either way if you have two threads accessing / updating the same data structure then they need to synchronize for the application to be reliable / portable.
Am i right for the beginning step with use Thread[] to collect all item from the threads?
It is one approach. But there are better approaches.
Is it useful to use thread join()?
If you are going to try to address this problem at this level, then it could be useful.
The problem is that your code doesn't give me much confidence that you have a clear idea of what you are doing. Or to put it another way, there is no evidence of a design. And it is not really possible to give you specific advice if we can't figure out how you think your code should work. The code certainly doesn't seem to line up with the things you are saying at the start of your question ...
The Second way to answer this is that from Java 5 onwards, the "java.util.concurrent" package provides a broad range of "off the shelf" components for implementing multi-threaded systems. What you seem to be trying to implement sounds like a good match for an ExecutorService. It can deal with all of the low-level details of creating and managing threads, and allows the application to get the results of each computation back via a Future. This takes away the need for explicit synchronization ... the ExecutorService and Future implementations take care of that.
So, my recommendation would be to read the Javadocs for ExecutorService, etcetera and figure out how to do what you are trying to do using that. Your code is likely to be better if you do it that way.