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
Related
Is there a way to safely and immediately stop the execution of a Thread in Java? Especially, if the logic inside the run() method of the Runnable implementation executes only a single iteration and does not regularly check for any flag that tells it to stop?
I am building a Web Application, using which a user can translate the contents of an entire document from one language to another.
Assuming the documents are extra-large, and subsequently assuming each translation is going to take a long time (say 20-25 minutes), my application creates a separate Thread for each translation that is initiated by its users. A user can see a list of active translations and decide to stop a particular translation job if he/she wishes so.
This is my Translator.java
public class Translator {
public void translate(File file, String sourceLanguage, String targetLanguage) {
//Translation happens here
//.......
//Translation ends and a new File is created.
}
}
I have created a TranslatorRunnable class which implements the Runnable interface as follows:
public class TranslatorRunnable implements Runnable {
private File document;
private String sourceLanguage;
private String targetLanguage;
public TranslatorRunnable(File document, String sourceLanguage, String targetLanguage) {
this.document = document;
this.sourceLanguage = sourceLanguage;
this.targetLanguage = targetLanguage;
}
public void run() {
// TODO Auto-generated method stub
Translator translator = new Translator();
translator.translate(this.document, this.sourceLanguage, this.targetLanguage);
System.out.println("Translator thread is finished.");
}
}
I'm creating the thread for translating a document from an outer class like this:
TranslatorRunnable tRunnable = new TranslatorRunnable(document, "ENGLISH", "FRENCH");
Thread t = new Thread(tRunnable);
t.start();
Now my problem is how do I stop a translation process (essentially a Thread) when the user clicks on "Stop" in the GUI?
I have read a few posts on StackOverflow as well as on other sites, which tell me to have a volatile boolean flag inside the Runnable implementation, which I should check on regularly from inside the run() method and decide when to stop. See this post
This doesn't work for me as the run() method is just calling the Translator.translate() method, which itself is going to take a long time. I have no option here.
The next thing I read is to use ExecutorService and use its shutDownAll() method. But even here, I'd have to handle InterruptedException somewhere regularly within my code. This, is again out of the option. Referred this documentation of the ExecutorService class.
I know I cannot use Thread.stop() as it is deprecated and may cause issues with objects that are commonly used by all threads.
What options do I have?
Is my requirement really feasible without substantial changes to my design? If yes, please tell me how.
If it is absolutely necessary for me to change the design, could anyone tell me what is the best approach I can take?
Thanks,
Sriram
Is there a way to safely and immediately stop the execution of a Thread in Java?
No. each thread is reponsible to periodically check if it has been interrupted to exit as soon as possible
if (Thread.currentThread().isInterrupted() ) {
// release resources. finish quickly what it was doing
}
if you want a more responsive application, you have to change the logic (for example divide each job in smaller batches) so each thread does this checking more often than every 20-25 minutes
If you are the one that created the Translator class what's stopping you from adding some kind of value inside the function that is checked periodically and if needed stops reading the lines from file something like this
public static List<String> readFile(String filename)
{
List<String> records = new ArrayList<>();
try
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null)
{
String[] split = line.split("\\s+");
records.addAll(Arrays.asList(split));
if (needsToStop) {
break; //Or throw exception
}
}
reader.close();
return records;
}
catch (Exception e)
{
System.err.format("Exception occurred trying to read '%s'.", filename);
e.printStackTrace();
return null;
}
}
public void taskInProgress(String jobMessage) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
runningTask = true;
Test:
while (runningTask) {
for (int i = 0; i < runningStars.length; i++) {
System.out.print(runningStars[i].concat(" ").concat(jobMessage));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
t.start();
}
public void taskFinnished(String msg) {
this.runningTask = false;
System.out.println("\r".concat(ok(msg)));
}
The wished effect is, that stars get printed as an infinite progress bar in the console, that is the for loop nested in the while loop, and when i call a method, the stars get replaced with a status and message, and they get stopped. I implemented this with latching the class field runningTask in taskFinnished().
My problem is, even after breaking the while loop, stars still get printed to the console. The loop continues execution even after the while loop condition returns false, for a good few seconds.
Screenshot:
As seen here, it still says Extracting tar archive, after the taskFinnished() method has been called and the while loop broken.
Here is the code that uses these implementations:
tc.taskInProgress("Extracting tar archive");
// do long operation on main thread, keep console animation running in seperate thread, and return exit int, Unix style
if (exit == 0) {
tc.taskFinnished("Tar finished without errors");
// This breaks the while loop, but more stuff gets printed even after breaking loop
} else {
// failed, handle it
}
Try to replace
for (int i = 0; i < runningStars.length; i++)
with
for (int i = 0; i < runningStars.length && runningTask; i++)
Your boolean flag (runningTask) must be declared volatile. Otherwise, there is no guarantee that the running thread sees the change made by the main thread.
An alternative would be to use an AtomicBoolean instead. But even better, you should use the mechanism that already exists to ask threads to stop running: interrupting the thread (by calling interrupt() on it). The running thread would have to regularly check if the current thread has been interrupted, using Thread.currentThread().isInterrupted().
The advantage of this mechanism over a custom boolean flag is that it the running thread is blocked waiting or sleeping, it will immediately go out of its waiting/sleeping state, by throwing an InterruptedException.
You should catch that exception, but instead of just ignoring it as you're doing, you should instead stop running ASAP.
I got a NullPointerException in my project and I would like to evaluate what is the sevirity of this issue. The exception is thrown just before the thread finished its task and going to die anyway.
My code failed to catch this excepition, so the thread is dead.
Here is a simple simulation of the situation:
public class Test extends Thread {
public static void main(String[] args) throws InterruptedException {
Test thread = new Test();
thread.start();
while(true) {
System.out.println("I'm still here!");
Thread.sleep(1000);
}
}
public void run() {
String s = null;
int len = s.length(); // causes NullPinterException
}
}
My question is: What is going to happened to this poor thread now? Is its linux file descriptor get freed? Is there any stability or memroy issues that may occur in such kind of code?
The handling is not different than with any other terminated thread. The one thing that happens before is the search for an UncaughtExceptionHandler according to the rules (specific Thread, ThreadGroup, all threads) but apart from this the "normal" cleanup procedure follows. There are no specific consequences regarding sytem resources (depending on the Thread implementation) or memory issues when a thread is terminated by an uncaught exception in contrast to a "normal" termination.
This is not about threads at all. Look at your code:
String s = null;
int len = s.length();
When you are calling s.length() the s is indeed null that causes NullPointerException.
Assign some value to s and you will get its length.
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.
I have a problem with the console output of one of my threads being dropped (in Java). The situation is as follows: I spawn a thread that listens (using a blocking method) for incoming messages. These messages are then asynchronously written to the console. Meanwhile, I read in the user input on the console via System.console().readLine().
The problem is that the text is never written to the console at all. I mean, as the readLine() method is blocking, I would have expected the console at least to show the output that has been written to the console as soon as something is entered in the main thread.. Or am I missing the point here?
The relevant source is
// ...
// handle receiving messages
(new Thread() {
#Override
public void run() {
while (executing) received(new String(subSocket.recv(0)));
}
}).start();
// ...
String input;
try {
while ((input = System.console().readLine()) != null && !input.equals(".")) {
pubSocket.send(input.getBytes(), 0);
Thread.yield();
}
}
catch (Exception ex) { }
finally {executing = false;}
And the received method is
public void received(String s) {
System.console().format("(%s)", s);
System.console().flush();
}
What am I doing wrong? Or is there a better way to do this? I mean, I tried to use a BufferedReader encapsulating the input stream in order to read it linewise and used System.out.format() along with it.. To the same effect - Nothing :(.
Cheers,
fxx
Try something like,
Implement a thread to read from input and store it in synchronized map/vector/list etc..
Another thread is listening on that collection, which will then process the message.
I think this should help in some way... Main thing is, don't run the loop on system input. Give it a try.