Java - How to safely stop a thread in a web application from a GUI?
Is there a way to safely and immediately stop Thread execution in Java? In particular, if the logic inside the run()
implementation method onlyRunnable
does one iteration and does not regularly check any flag that tells it to stop?
I am creating a web application using which a user can translate the content of an entire document from one language to another.
Assuming the documents are very large and therefore each translation will take a long time (say 20-25 minutes), my application creates a separate thread for each translation initiated by its users. The user can see a list of active translations and decides to stop a specific translation job if he so desires.
This is my .java translator
public class Translator {
public void translate(File file, String sourceLanguage, String targetLanguage) {
//Translation happens here
//.......
//Translation ends and a new File is created.
}
}
I created a class TranslatorRunnable
that implements the interface Runnable
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 am creating a stream to translate a document from an external class like this:
TranslatorRunnable tRunnable = new TranslatorRunnable(document, "ENGLISH", "FRENCH");
Thread t = new Thread(tRunnable);
t.start();
Now my problem is how to stop the translation process (essentially a thread) when the user clicks "Stop" in the GUI?
I read several posts on StackOverflow as well as other sites that say I have a flag volatile boolean
inside the implementation Runnable
that I have to check regularly from the method run()
and decide when to stop. See this post
This doesn't work for me, as the run () method just calls the Translator.translate () method, which itself will take a long time. I have no choice here.
The next thing I read was to use ExecutorService
and use his method shutDownAll()
. But even here I will have to process InterruptedException
somewhere regularly in my code. Again, this is not an option. Recalls that documentation ExecutorService class.
I know I cannot use Thread.stop()
as it is deprecated and can cause problems with objects that are commonly used by all threads.
What options do I have?
Is my requirement really doable without significant changes to my design? If so, please tell us.
If I absolutely need to redesign, can someone tell me what is the best approach I can take?
Thanks, Sriram
source to share
Is there a way to safely and immediately stop Thread execution in Java?
Not. each thread is responsible for checking periodically if it was 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 need to change the logic (for example, divide each job into smaller batches) so that each thread performs this check more often than every 20-25 minutes.
source to share
If you created the Translator class, which prevents you from adding some value inside a function that is periodically checked and, if necessary, stops reading lines from the 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;
}
}
source to share