public class MultiThreadExample extends Thread {
public static int count=0;
static String s="";
synchronized public static String read(){
String line="";
System.out.println("Enter new line:");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
try {
line=br.readLine();
count++;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return line;
}
synchronized public static void write(String line){
try {
BufferedWriter br=new BufferedWriter(new FileWriter("C://name.txt"));
br.write(line);
System.out.println(line);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run(){
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
th2.start();
}
}
The count check in run() method is not working. Any idea why? The count increases with each call, I can see, but the check is not working, and each time the control passes to read() method, and does not go to write()
What am I doing wrong? Also, is there any other efficient way to call multiple methods from a two threads, depending on situation?
P.S. I am trying to read input using one thread, and write the input value to a file in another thread
try this:
MultiThreadExample th1=new MultiThreadExample();
MultiThreadExample th2=new MultiThreadExample();
th1.start();
try {
th1.join();
} catch (InterruptedException ex) {
System.out.println(ex.getMessage());
}
th2.start();
Don't create a new BufferedReader for every line. Use the same one for the life of the socket. You're losing data read-ahead by each BufferedReader.
Remove all the static except main method ... All you need to ensure is that read and write don't change/read "count" at the same time ... Use a different lock object like "lockObject" and use wait() and notify(). You are looking for a producer/consumer sort of a pattern here. Here is an example: http://www.programcreek.com/2009/02/notify-and-wait-example/
can also try 'similar' approach. , which ever thread enters first reads, and the later one waits for the former to read and then it writes. (it doesn't need your static methods to be synchronized)
static ReentrantLock l = new ReentrantLock();
public void run(){
l.lock();
if(count==0){
System.out.println("Read " + s + " Count " + count);
s=read();
l.unlock();
System.out.println("Read " + s + " Count " + count);
}
else{
write(s);
System.out.println("Write" + s + " Count " + count);
}
}
Okay, can you please explain to me, why my previous code was not working, and the check failed?
#Shail016 explained it in a comment on your question. Here's one possible sequence of events.
main thread calls th1.start(), calls th2.start(), and then exits.
thread 1 enters the run() method, sees that count==0, enters the read() method, calls System.out.println(...)
thread 2 enters the run() method, sees that count==0, tries to enter the read() method, gets blocked, waiting for the mutex.
thread 1 returns from the System.out.println(...) call, reads a line, increments count, and returns,
thread 2 is allowed in to read(), etc., etc.,
etc.
etc.
Mark count as volatile. This ensures that changes from one thread are seen by other threads. As long as only one thread updates count, this is OK, otherwise, you could use either an AtomicInteger, an AtomicIntegerFieldUpdater in conjunction with a volatile field or (if you measure high contention, which is unlikely in your case) a LongAdder (all classes are from the java.util.concurrent.atomic package, the last is only available in Java 8).
Related
public static void main() {
String fileName = "cardNumbers.txt";
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null)
{
CreditCard card = new CreditCard(line);
if (card.creditCardType().equalsIgnoreCase("Unknown"))
{
System.out.println("Card number " + card.getCardNumber() + "is an unknown credit card type.");
}
else if (card.isValid())
{
System.out.println(card.creditCardType() + " number" + card.getCardNumber() + " is valid.");
}
else if (!card.isValid())
{
System.out.println(card.creditCardType() + " number " + card.getCardNumber() + " is not valid.");
}
}
}
catch (FileNotFoundException ex)
{
System.out.println("file not found exception thrown");
}
catch (IOException ex)
{
System.out.println("error while reading the file");
}
finally
{
System.exit(0);
}
}
When I run this method it just says ProcessCardNumbers.main(); VM Terminated. Instead of actually printing out the content.
If I add a print at the very start of the function or in the finally block, they are printed.
Im not sure why this is happening or how I can fix it.
As you told us that:
Adding a println at the start is printed
and
Adding a println in the finally works too
we can deduce that your code is working. It's just that when you reach while((line = bufferedReader.readLine()) != null), line stays null, so you never enter your while.
Why is that? Well, your file may be empty to begin with. If it is not, double-check the encoding of your file: it may not be using the proper returns symbols, hence not having a "completed line".
This seems that in your text file cardNumbers.txt has no data. When this program will execute within while loop bufferedReader.readLine()). will return null. So loop will terminate. After termination you have written System.exit(0); function in finally block which terminate JVM on the spot. So JVM is terminated now that's why you are not able to see anything after working of this code.
If you want to check working, write one SOP statement in finally block. Probably that will execute without termination of JVM.
The problem here is not the bug in your code but the design problem that does not let you see the bug.
You are probably getting an undeclared exception (RuntimeException) and the VM can't print it because you kill it before in the finally.
You have several options:
Remove the System.exit(0); and let it die normally. This may fail if there is another non-daemon thread running. You may try to stop it. You can, for example, cancel a Timer.
Add a catch (RuntimeException e) { section before the finally and print the captured error. e.printStackTrace(); should do the trick.
With any of those you should see the exception on console so you can fix it.
Your main method signature must look like this:
public static void main(String[] args)
instead of
public static void main()
For learning purposes, I am implementing UDP with the mechanisms of TCP (so that it guarantees safe transfer).
The Semaphore I am using is binary, so its sem = new Semaphore(1);.
I use this semaphore to control the entrance for my sendBuf, which is a List containing all packages which have been send, but not yet confirmed. Since I sometimes remove packages out of it when I get an ACK, I need to make sure I am not iterating with one thread while another thread is deleting something out of it.
The thing which is really bugging me is this:
public void timeoutTask(long seqNum) {
System.out.println("Timeout for package with SeqNum " + seqNum
+ " happened.");
timeoutValue *= 2;
try {
System.out.println("Acquire? in timeouttask");
sem.acquire();
System.out.println("Acquired! in timeouttask");
} catch (InterruptedException e1) {
System.out.println("semaphore not acquired");
e1.printStackTrace();
}for (FCpacket packet : sendBuf) {
System.out.println("Iterating!");
if (packet.getSeqNum() == seqNum) {
System.out.println("Package for seqNum " + seqNum + " found!");
reSendData = packet.getSeqNumBytesAndData();
DatagramPacket reSendPacket = new DatagramPacket(reSendData,
reSendData.length, hostaddress, SERVER_PORT);
try {
clientSocket.send(reSendPacket);
System.out.println("Packet with seq " + seqNum
+ " send again");
packet.setTimestamp(0);
startTimer(packet);
new ReceiveHandler(reSendData, reSendData.length,
clientSocket, rcvData, UDP_PACKET_SIZE, this).run();
} catch (IOException e) {
System.out.println("Couldn't send package");
e.printStackTrace();
}
}
}
sem.release();
System.out.println("released! in timeouttask");
Console output gives me the following:
Acquire? in timeouttask
Acquired! in timeouttask
Iterating!
Paket for seqNum 1 found!
Packet with seq 1 send again
So it gets the semaphore, starts iterating, it even sends the package, so by now it should Either: Iterate again ("iterating!") OR release the semaphore. None of the above happens, it is just stuck. I have no idea why - any ideas?
If ReceiveHandler is a Thread, it should be invoked as
new ReceiveHandler(reSendData, reSendData.length, clientSocket, rcvData, UDP_PACKET_SIZE, this).start();
But if it is a Runnable, it should be invoked as
new Thread(new ReceiveHandler(reSendData, reSendData.length, clientSocket, rcvData, UDP_PACKET_SIZE, this)).start();
run() will not execute the task in a separate Thread.
see: What's the difference between Thread start() and Runnable run()
I am trying to setup a 2 way publisher-subscriber using the WatchService in NIO.
I'm not terribly experienced with threads, so if I'm not making any sense feel free to call me out on it!
This is only a sample to figure out how the library works, but the production code is going to listen for a change in an input file, and when the file changes it will do some calculations and then write to an output file. This output file will be read by another program, some calculations will be run on it. The input file will then be written to and the cycle continues.
For this test though, I am making 2 threads with watchers, the first thread listens on first.txt and writes to second.txt, and the second thread waits on second.txt and writes to first.txt. All that I am doing is incrementing a count variable and writing to each thread's output file. Both of the threads have blocking calls and filters on what files they actually care about, so I figured the behavior would look like
Both threads are waiting on take() call.
Change first.txt to start the process
This triggers the first thread to change second.txt
Which then triggers the second thread to change first.txt
and so on.
Or so I hoped. The end result is that the threads get way out of sync and when I do this for count up to 1000, one thread is usually behind by more than 50 points.
Here is the code for the watcher
Watcher(Path input, Path output) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.input = input;
this.output = output;
dir = input.getParent();
dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
}
void watchAndRespond() throws IOException, InterruptedException {
while (count < 1000) {
WatchKey key = watcher.take();
for (WatchEvent<?> event: key.pollEvents()) {
if (! event.context().equals(input.getFileName())) {
continue;
}
WatchEvent.Kind kind = event.kind();
if (kind == OVERFLOW) {
continue;
}
count++;
try (BufferedWriter out = new BufferedWriter(new FileWriter(output.toFile()))) {
out.write(count + "");
}
}
key.reset();
}
}
I don't want to have to read the file to decide whether or not the file has changed, because these files in production could potentially be large.
I feel like maybe it is too complicated and I'm trying to deal with a scraped knee with amputation. Am I using this library incorrectly? Am I using the wrong tool for this job, and if so are there any other file listening libraries that I can use so I don't have to do polling for last edited?
EDIT:
Oops, here is the test I wrote that sets up the two threads
#Test
public void when_two_watchers_run_together_they_end_up_with_same_number_of_evaluation() throws InterruptedException, IOException {
//setup
Path input = environment.loadResourceAt("input.txt").asPath();
Path output = environment.loadResourceAt("output.txt").asPath();
if (Files.exists(input)) {
Files.delete(input);
}
if (Files.exists(output)) {
Files.delete(output);
}
Thread thread1 = makeThread(input, output, "watching input");
Thread thread2 = makeThread(output, input, "watching output");
//act
thread1.start();
thread2.start();
Thread.sleep(50);
BufferedWriter out = new BufferedWriter(new FileWriter(input.toFile()));
out.write(0 + "");
out.close();
thread1.join();
thread2.join();
int inputResult = Integer.parseInt(Files.readAllLines(input).get(0));
int outputResult = Integer.parseInt(Files.readAllLines(output).get(0));
//assert
assertThat(inputResult).describedAs("Expected is output file, Actual is input file").isEqualTo(outputResult);
}
public Thread makeThread(Path input, Path output, String threadName) {
return new Thread(() ->
{
try {
new Watcher(input, output).watchAndRespond();
}
catch (IOException | InterruptedException e) {
fail();
}
}, threadName);
}
I think the problem is that some of the modifications are putting multiple events into the queue and at this point I have no way to discern whether or not they are 2 events that were created by one save or 2 separate saves.
The tool seems to be quite right but your code will have to be flow in sequence else everything is going to be out of sync as you have noticed.
Look at it as a transaction which has to be completed before another transaction starts.
In this case the transaction can boil down to
1.) Detect File1 change
2.) Modify File2
3.) Detect File2 change
4.) Modify File1
So before this cycle ends completely if another cycle starts then there will be trouble. When you are using Threads, the scheduling and execution is not entirely predictable so you would not know what your 2 threads are doing.
Whether they are doing things sequentially as per your requirements.
So you would have to share your Thread code for anyone to give a specific
solution.
Another point is can you keep a small change file which contains the change
and use that instead of using the bigger production file. That
way you can reduce the focus to a smaller object.
Here is something more specific I noticed after running your code.
Its quite fine...some points though...there is no need for
thread1.join();
thread2.join();
Both the threads are required to run concurrently so join is not
needed.
For your main question ...the threads are out of sync because they
are connected to their own watcher objects and so the count value
is different for both the threads.
So depending on how the scheduler runs the threads...one of them
will get more mileage and will reach count 1000 first while the
other is still lagging behind.
I am editing in response to your comment....Take is a blocking call and
it is working perfectly. In my case the only event trapped is ENTRY_MODIFY
so no multiple event issue.
One tip is you can set dir.register(watcher, ENTRY_MODIFY); in code
to check only for modify events. Please see my code below..also
my printlns may help to get better understanding of the code flow.
public class WatcherTest {
public static void main(String args[]) throws InterruptedException, IOException {
Path input = FileSystems.getDefault().getPath("txt", "input.txt");
Path output = FileSystems.getDefault().getPath("txt", "output.txt");
if (Files.exists(input)) {
Files.delete(input);
}
if (Files.exists(output)) {
Files.delete(output);
}
Thread thread1 = new Thread(new WatchFileTask(input, output ), "ThreadToOpt");
Thread thread2 = new Thread(new WatchFileTask(output, input ), "ThreadToInpt");
thread1.start();
thread2.start();
Thread.sleep(100);
BufferedWriter out = new BufferedWriter(new FileWriter(input.toFile()));
out.write(0 + "");
out.close();
//thread1.join();
//thread2.join();
//int inputResult = Integer.parseInt(Files.readAllLines(input, Charset.defaultCharset()).get(0));
// int outputResult = Integer.parseInt(Files.readAllLines(output, Charset.defaultCharset()).get(0));
}
}
class FileWatcherService {
private WatchService watcher;
private Path input;
private Path output;
private Path dir;
private int count = 0;
FileWatcherService(Path input, Path output) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.input = input;
this.output = output;
Path dir = input.getParent();
dir.register(watcher, ENTRY_MODIFY);
}
void watchAndRespond() throws IOException, InterruptedException {
while (count < 1000) {
System.out.println("\n COUNT IS " + count + " in Thread " + Thread.currentThread().getName());
System.out.println("\n Blocking on Take in Thread " + Thread.currentThread().getName());
WatchKey key = watcher.take();
System.out.println("\n Out of Blocking State " + Thread.currentThread().getName());
int eventsPassed = 0;
for (WatchEvent<?> event: key.pollEvents()) {
if (!event.context().equals(input.getFileName())) {
continue;
}
System.out.println("\n File Context : " + event.context() + " Event Kind " + event.kind() + " in Thread " + Thread.currentThread().getName());
WatchEvent.Kind kind = event.kind();
if (kind == OVERFLOW) {
continue;
}
eventsPassed++;
count++;
//synchronized(output){
try (BufferedWriter out = new BufferedWriter(new FileWriter(output.toFile()))) {
out.write(count + "");
System.out.println("\n Wrote count : " + count + " to File " + output.getFileName() + " in Thread " + Thread.currentThread().getName());
}
// }
}
System.out.println("\n The eventsPassed counter is " + eventsPassed + " \n for thread " + Thread.currentThread().getName());
key.reset();
}
}
}
I'm using RXTX to read data from a serial port. The reading is done within a thread spawned in the following manner:
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(port);
CommPort comm = portIdentifier.open("Whatever", 2000);
SerialPort serial = (SerialPort)comm;
...settings
Thread t = new Thread(new SerialReader(serial.getInputStream()));
t.start();
The SerialReader class implements Runnable and just loops indefinitely, reading from the port and constructing the data into useful packages before sending it off to other applications. However, I've reduced it down to the following simplicity:
public void run() {
ReadableByteChannel byteChan = Channels.newChannel(in); //in = InputStream passed to SerialReader
ByteBuffer buffer = ByteBuffer.allocate(100);
while (true) {
try {
byteChan.read(buffer);
} catch (Exception e) {
System.out.println(e);
}
}
}
When a user clicks a stop button, the following functionality fires that should in theory close the input stream and break out of the blocking byteChan.read(buffer) call. The code is as follows:
public void stop() {
t.interrupt();
serial.close();
}
However, when I run this code, I never get a ClosedByInterruptException, which SHOULD fire once the input stream closes. Furthermore, the execution blocks on the call to serial.close() -- because the underlying input stream is still blocking on the read call. I've tried replacing the interrupt call with byteChan.close(), which should then cause an AsynchronousCloseException, however, I'm getting the same results.
Any help on what I'm missing would be greatly appreciated.
You can't make a stream that doesn't support interruptible I/O into an InterruptibleChannel simply by wrapping it (and, anyway, ReadableByteChannel doesn't extend InterruptibleChannel).
You have to look at the contract of the underlying InputStream. What does SerialPort.getInputStream() say about the interruptibility of its result? If it doesn't say anything, you should assume that it ignores interrupts.
For any I/O that doesn't explicitly support interruptibility, the only option is generally closing the stream from another thread. This may immediately raise an IOException (though it might not be an AsynchronousCloseException) in the thread blocked on a call to the stream.
However, even this is extremely dependent on the implementation of the InputStream—and the underlying OS can be a factor too.
Note the source code comment on the ReadableByteChannelImpl class returned by newChannel():
private static class ReadableByteChannelImpl
extends AbstractInterruptibleChannel // Not really interruptible
implements ReadableByteChannel
{
InputStream in;
⋮
The RXTX SerialInputStream (what is returned by the serial.getInputStream() call) supports a timeout scheme that ended up solving all my problems. Adding the following before creating the new SerialReader object causes the reads to no longer block indefinitely:
serial.enableReceiveTimeout(1000);
Within the SerialReader object, I had to change a few things around to read directly from the InputStream instead of creating the ReadableByteChannel, but now, I can stop and restart the reader without issue.
i am using the code below to shutdown rxtx. i run tests that start them up and shut them down and the seems to work ok. my reader looks like:
private void addPartsToQueue(final InputStream inputStream) {
byte[] buffer = new byte[1024];
int len = -1;
boolean first = true;
// the read can throw
try {
while ((len = inputStream.read(buffer)) > -1) {
if (len > 0) {
if (first) {
first = false;
t0 = System.currentTimeMillis();
} else
t1 = System.currentTimeMillis();
final String part = new String(new String(buffer, 0, len));
queue.add(part);
//System.out.println(part + " " + (t1 - t0));
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
//System.out.println(Thread.currentThread().getName() + " interrupted " + e);
break;
}
}
} catch (IOException e) {
System.err.println(Thread.currentThread().getName() + " " + e);
//if(interruSystem.err.println(e);
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName() + " is ending.");
}
thanks
public void shutdown(final Device device) {
shutdown(serialReaderThread);
shutdown(messageAssemblerThread);
serialPort.close();
if (device != null)
device.setSerialPort(null);
}
public static void shutdown(final Thread thread) {
if (thread != null) {
//System.out.println("before intterupt() on thread " + thread.getName() + ", it's state is " + thread.getState());
thread.interrupt();
//System.out.println("after intterupt() on thread " + thread.getName() + ", it's state is " + thread.getState());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " was interrupted trying to sleep after interrupting" + thread.getName() + " " + e);
}
//System.out.println("before join() on thread " + thread.getName() + ", it's state is " + thread.getState());
try {
thread.join();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " join interruped");
}
//System.out.println(Thread.currentThread().getName() + " after join() on thread " + thread.getName() + ", it's state is" + thread.getState());
}
I'm writing my first non-trivial Java app that uses:
networking
a GUI
threads
It's a IM program. When I send a message, the server doesn't output what it should. I'm sorry this description is so bad, but I don't know how to narrow the problem down further.
public class MachatServer {
//snip
public static void sendMessage(int targetId, int fromId, String message) {
ConnectedClient targetClient = getClient(targetId);
// Also runs
System.out.println("Sending message: " + message + "\n\nfrom " + fromId + " to " + targetId);
targetClient.addOutCommand("/message:" + fromId + ":" + message + "\n");
}
}
class ConnectedClient implements Runnable {
public void run() {
String contact;
contact = s.getInetAddress().toString();
System.out.println("Connected to " + contact);
try {
out.write("/connected" + "\n");
out.flush();
String command;
while(true) {
if(shouldExit) {
s.close();
break;
}
if(in.hasNextLine()) {
command = in.nextLine();
commandProcessor.addInCommand(command);
}
Thread.sleep(100);
}
} catch(Exception e) {
e.printStackTrace();
}
}
// snip
public void addOutCommand(String command) {
commandProcessor.addOutCommand(command);
//
// My guess is that the problem is with this method as the next line
// Does not print out.
//
//
System.out.println("" + thisId + " recieved to send: " + command);
}
}
class CommandProcessor implements Runnable {
// snip
public void run() {
String currentCommandIn;
String currentCommandOut;
while(true) {
try {
currentCommandIn = inQueue.poll();
if(currentCommandIn != null) {
System.out.println("Processing: " + currentCommandIn);
String[] commandArr = CommandParser.parseRecievedCommand(currentCommandIn);
if(commandArr[0].equalsIgnoreCase("message")) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
// This definetly runs
System.out.println("Message sending to: " + target);
MachatServer.sendMessage(target, this.conId, message);
} else if(commandArr[0].equalsIgnoreCase("quit")) {
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
break;
}
currentCommandOut = outQueue.poll();
if(currentCommandOut != null) {
try {
out.write(currentCommandOut + "\n");
System.out.println(currentCommandOut + "sent");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
}
public synchronized void addOutCommand(String command) {
if(command != null) {
try {
outQueue.push(command);
} catch(Exception e) {
System.out.println(command);
e.printStackTrace();
}
// Does not print
System.out.println("Ready to send: " + command);
} else {
System.out.println("Null command recieved");
}
//snip
}
The full source code is at my github, in case I have narrowed the problem down incorrectly.
The expected output should be when I telnet in and send "/message:0:test", it should send "/message:myid:test" to the client with ID 0. The actual output is nothing.
This is probably not a complete answer, but there are a few serious issues with your code that could be the cause of your problem, so you should fix those first.
First, the loop in CommandProcessor.run is busy-waiting, i.e., it runs constantly. You should use blocking operations. Also, inQueue and outQueue are accessed from two different threads so you need synchronization on every access. I recommend using something implementing the java.util.concurrent.BlockingQueue interface to solve both issues. And finally, when checking your full code, it appears that you also need to synchronize access to the ConnedtedClient.shouldExit field (I believe you can use `java.util.concurrent.atomic.AtomicBoolean as a replacement but I'm not sure).
And the reason why this could be the cause of your problem: Since CommandProcessor.run is not synchronizing on anything (or accessing anything volatile), the Java virtual machine can assume that nothing from outside can modify anything it examines, so in theory, when the run method first notices that inQueue and outQueue are both empty, it can optimize the whole method into nothing, as it can assume that it is the only thing that can modify them. But I don't know whether this can actually happen in practice, as the JVM needs to know quite a bit about the LinkedList implementation and notice that the thread is just doing these two checks in a loop. But it's always best to be safe because that way your code is guaranteed to work.
The field outQueue is uninitialized in CommandProcessor, and you commented out the printStackTrace() that would have helped you figure it out.
Maybe the problem is that the data you send is to short....
A friend of mine had a similar problem a couple of years ago, and it turned out the data was being buffered until it had enough data to send...
It had something to do with optimizing the amount of network traffic... I believe he mentioned something called "Nagle's algorithm" when he finally solved it....
Hope this can be of some help...