Killing processes within Runnables - java

I am working on a Java program that opens multiple instances of a command line concurrently. To do this, I am using Threads with Runnables as shown here:
//Handles the command line running
private Process p;
private String port;
private String path;
#Override
public void run() {
ProcessBuilder pb = //Initialization of ProcessBuilder
pb.directory(new File(this.path));
...
try {
p = pb.start();
p.waitFor(); //Using this since the server must continue after it is started.
... //This is the part I need to cancel when I close the thread.
}
} catch (IOException e) { //These exceptions are thrown from the process inside the Runnable.
...
} catch (InterruptedException e) {
...
}
}
public void stopServer() {
p.destroy();
}
And in my Main application class:
ArrayList<Thread> threads = new ArrayList<>();
public void startServer(String port, String path) {
//Instantiate my Runnable Class, with port and path parameters
MyRunnable rss = new MyRunnable(port, path);
//Spawn a new thread with the Runnable
Thread thread = new Thread(rss);
//Set the name of the thread (presumably for finding it later?)
thread.setName("server-" + threads.size());
//Start the thread.
thread.start();
//Add the thread to an ArrayList<Thread>?
threads.add(thread);
}
So my question is: How do I use my stopServer() method to stop the process from the Main class?
Disclaimer: I'm very new to Multithreaded programming, so any help you can give would be awesome, there may be something simple that I simply do not know about how Threads work.
Thank you!

Instead of ArrayList<Thread>, I'd instead use ArrayList<MyRunnable>.
This way, I could iterate through the list calling stopServer() if the object is not null.

Related

A thread that runs without stopping

Is it possible in java to create a thread that will always work in the background? The problem is that the application instance sometimes crashes with an OutOfMemoryException. Therefore, several instances are launched in parallel. Each instance does some work: it saves something to the database at the request of the user. And the stream, which should work constantly, will look into the database and somehow process the information from it.
Most likely, the sheduler will not work, since the thread must be running constantly and wait for a signal to start working.
First of all, I suggest you investigate and resolve the OutOfMemoryException because it better to avoid these cases. You can instanziate a thread that wait for a request, execute a request and then return to wait for another request. The implementation is like this for thread:
/** Squares integers. */
public class Squarer {
private final BlockingQueue<Integer> in;
private final BlockingQueue<SquareResult> out;
public Squarer(BlockingQueue<Integer> requests,
BlockingQueue<SquareResult> replies) {
this.in = requests;
this.out = replies;
}
public void start() {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
// block until a request arrives
int x = in.take();
// compute the answer and send it back
int y = x * x;
out.put(new SquareResult(x, y));
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
}
}
And for the caller method:
public static void main(String[] args) {
BlockingQueue<Integer> requests = new LinkedBlockingQueue<>();
BlockingQueue<SquareResult> replies = new LinkedBlockingQueue<>();
Squarer squarer = new Squarer(requests, replies);
squarer.start();
try {
// make a request
requests.put(42);
// ... maybe do something concurrently ...
// read the reply
System.out.println(replies.take());
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
To more information, you can start to read the post that I found here to provide you the example.
You basically need an infinitely running thread with some control.
I found this answer to be the simplest and it does what you need.
https://stackoverflow.com/a/2854890/11226302

Thread does not stopped using flag as volatile

In following code i am trying to start and stop the server on button using java applet.Start works good using thread but i want to stop the server on button. I have used volatile variable.Still i am not getting the server stop..
here is code:
public class TCPServer extends Thread {
public static final int SERVERPORT = 8002;
private boolean running = false;
public volatile boolean stop = false;
public Socket client = null;
public static void main(String[] args) {
ServerBoard frame = new ServerBoard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public void run() {
super.run();
running = true;
try {
System.out.println("Server Has Started........ \n Waiting for client........");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
try {
while (!stop && running) {
client = serverSocket.accept();
System.out.println("Connection Accepted......");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String usercmnd = in.readLine();
if (usercmnd != null) {
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(usercmnd);
}
}
if (stop) {
serverSocket.close();
client.close();
System.out.println("Server Has Stopped");
System.exit(0);
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
public void requestStop() {
stop = true;
}
}
But whenever i click the stop button which will stop the server.Its not showing any output on console as i expected by the code.Its also not showing any error
here is code of stop button
stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stopServer.setEnabled(false);
startServer.setEnabled(true);
mServer = new TCPServer();
mServer.requestStop();
}
});
It doesn't stop because you create a new instance before stopping it and you don't even start it first while you are supposed to call requestStop() on your current instance of TCPServer.
// Here you create a new instance instead of using the existing one
mServer = new TCPServer();
mServer.requestStop();
in your ActionListener implementation for the stop button, you are accessing a different instance of TCPServer (as you are creating a new one). So you set the value "Stop" to a second object. It has no impact on the first instance that was created with the start button.
Try to instanciate the TCServer outside of your implementation of the action listener for both buttons and use that single instance for both.
Due to https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#accept()
ServerSocket::accept is a blocking method, so stop variable can only be checked between successful connections.
You can either set a ServerSocket timeout using ServerSocket::setSoTimeout (and catch SocketTimeoutException), or interrupt Server thread and catch InterruptedException.
Both exceptions will be throwed from ServerSocket::accept.
Note, that thread interruption is highly preferred over timeouts and repeatly exception catching.
Try this:
public void requestStop() {
stop = true;
interrupt();
}
However, in this case, we can not guarantee, that already processing logic will successfully shutdown.
Also, you try invoke requestStop for new instance of TCPServer, instead already existing.
your code client = serverSocket.accept(); is blocking. So once you clicked "stopServer" button, you requested the stop, but it will be acted upon only once a client sends a next request to the server. What you need to do is to run your logic in your method run() in a separate thread and catch there InterruptedException and ClosedByInterruptException and clean up and return there. On your stopButton click you will invoke interrupt() method on your Thread. Read about it in here

Stopping a running process via GUI, in java

I have a GUI program that executes TestNG automation scripts. It's meant for users to easily configure some setting and launch the automation script that they want.
One thing I need to add is the ability to instantly stop the running TestNG process. Something like how in Eclipse, the 'Terminate' button will instantly stop whatever is running.
This is what the code that launches the TestNG tests looks like:
public class ScriptRunner implements Runnable {
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
As per the comment, the tng.run() can take several minutes to complete, and it's performing several things, opening/closing browser windows, etc.
How can I just instantly terminate the process, like you would when running an application from an IDE?
EDIT:
Per the comments, I'm attempting to use a ServiceExecutor and shutDownNow() The code is looking like this:
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void runScript() {
executorService.execute(this);
}
//this method gets called when I click the "stop" button
public void stopRun() {
executorService.shutdownNow();
}
#Override
public void run() {
//same stuff as from earlier code
}
Spawn a child JVM process using ProcessBuilder or Runtime and you will be able to terminate that process when the user requests that the script stops running.
You can use ExecutorService to start test execution into one another thread. You can choose to have many thread in parrallel or juste one thread for all tests in sequence by choosing which executor service you need.
After that, start the execution of all tests in the same executor service instance by calling submit() method on it. You can stop the execution of all submitted runnables by calling shutdownNow() method.
It is important to use the same instance of ExecutorService, otherwise you start each test in a different thread and you will not enable to break the execution chain (or by calling shutdownNow() on all of them).
I was recently working on the executor framework. Here I have listed my problem
http://programtalk.com/java/executorservice-not-shutting-down/
Be careful if you are doing some IO operations the executor service may not shutdown immediately. If you see the below code stopThread is important because it tells your program that the thread has been asked to stop. And you can stop some iteration what you are doing.
I will modify your code like this:
public class MyClass {
private ExecutorService executorService;
private boolean stopThread = false;
public void start() {
// gives name to threads
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("thread-%d").build();
executorService = Executors.newSingleThreadExecutor(factory);
executorService.execute(new Runnable() {
#Override
public void run() {
try {
doTask();
} catch (Exception e) {
logger.error("indexing failed", e);
}
}
});
executorService.shutdown();
}
private void doTask() {
logger.info("start reindexing of my objects");
List<MyObjects> listOfMyObjects = new MyClass().getMyObjects();
for (MyObjects myObject : listOfMyObjects) {
if(stopThread){ // this is important to stop further indexing
return;
}
DbObject dbObjects = getDataFromDB();
// do some task
}
}
public void stop() {
this.stopThread = true;
if(executorService != null){
try {
// wait 1 second for closing all threads
executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
What about this,
add a volatile static boolean and make the thread code look like...
if(ScriptRunner.runThread){
//Do some stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do some other stuff here
}
if(ScriptRunner.runThread){
//Do rest of the stuff here
}
Now you can add a button in your main GUI that simply sets the runThread to false so the thread will terminate nearly instant leaving all the leftover code untouched as you press the Stop button.
public class ScriptRunner implements Runnable {
volatile static Boolean runThread = true;
public void runScript() {
Thread testRun = new Thread(this);
testRun.start();
}
public void terminate(){
runThread = false;
}
#Override
public void run() {
//various other things are configured for this,
//but they're not relevant so I left them out
TestNG tng = new TestNG();
//While this runs, various browser windows are open,
//and it could take several minutes for it all to finish
tng.run();
}
}
How about a new Thread? You have to add an private Thread thread; in the gui and when ever you start
thread = new thread(){
#Override
public void run(){
//start process here
}
};
thread.start();
and to stop "terminate"
thread.stop();(depracted) or thread.setDeamon(true);
Everytime I have to stop a process by the gui I use this.
Hope I could help ;)
In your GUI somewhere you have something like
ScriptRunner scriptRunner = new ScriptRunner();
scriptRunner.runScript();
When you want to stop it call
scriptRunner.interrupt();
Change the code in ScriptRunner
private Thread testRun;
public void runScript() {
testRun = new Thread(this);
testRun.start();
}
public void interrupt() {
testRun.interrupt();
}
Save all created processes and kill them when your program ends:
public class ProcessFactory {
private static Set<Process> processes = new HashSet<>();
private static boolean isRunning = true;
public static synchronized Process createProcess(...) throws ... {
if (!isRunning)
throw ...
... // create your spawned process
processes.add(process);
return process;
}
public static synchronized void killAll() {
isRunning = false;
for (Process p : processes)
p.destroy();
processes.clear();
}
public static void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
void run() {
killAll();
}
});
}
}
This can be improved by adding a mechanism that removes already dead processes, but you get the general idea.

Java Callable thread swing gui

Im missing something, I've created a calss based on callable and in my gui creating an instance and calling it when a action is performed. the only thing is that the GUI is unresponsive as the process is running on the same thread and has to wait for it to finish before I can access the GUI. Here is some of the Code:
public class MYProject {
public static class CreateProject implements Callable<Boolean>{
private String m_url;
private String m_project;
private String m_options;
public CreateProject(String url, String project, String options){
m_url = url;
m_project = project;
m_options = options;
}
public Boolean call(){
Boolean result = true;
try {
if (os.toLowerCase().contains("windows")){
command = windowsCMD + command;
}
String line;
Process p = Runtime.getRuntime().exec(command);
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader bri = new BufferedReader(isr);
try {
while ((line = bri.readLine()) != null) {
if(line.startsWith("ERROR")){
System.out.println(line);
result = false;
break;
}
}
p.waitFor();
}
finally {
bri.close();
}
}
catch (Exception err) {
System.err.println("Unable to create project: " + err.getMessage()
+ "\n");
result = false;
}
return result;
}
}
}
and in the GUI:
private void jButtonRefreshActionPerformed(java.awt.event.ActionEvent evt) {
jTextAreaConsole.append("Creating project.\n");
MYProject.CreateProject blah = new MYProject.CreateProject("url", "project", "options");
String result = blah.call();
jTextAreaConsole.append("Project creation successful: " + result);
}
The result being Process p is still running on the same thread as the gui and nothing is clickable and the jTextAreaConsole doesnt update until after the process has finished. Can any one offer some advice on how I should be implementing this?
Implement a SwingWorker for long running tasks. See Concurrency in Swing for more details.
The result being Process p is still running on the same thread as the
gui and nothing is clickable and the jTextAreaConsole
Yes it is doing exactly what p.waitFor(); in your code
waitFor()
Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
from
Process Class
You might want to use SwingWorker like #Andrew Thompson posted
Or you can implement RunnableĀ“s run method and start it in a new thread
Or even using the Executor class like #hoaz posted
For the callable to run in a separete thread you need to use Executors
You should use Executor to run your Callable instance in separate Thread.
Executor executor = Executors.newSingleThreadExecutor();
executor.submit(blah);
...
executor.shutdown(); // free resources
Note that you should create executor once and destroy it when your program quits. Otherwise you may leak resources.

How to safely close stream when using threads

I have thread with this code:
public void run() {
try {
fileProcessor = new FileProcessor();
fileProcessor.process();
} catch (RuntimeException e) {
// ...
} finally {
if (fileProcessor != null) {
fileProcessor.close();
}
}
}
method fileProcessor.process(); run some new thread too:
protected void process() {
this.writer = new Writer();
final MyClient client = new MyClient();
client.start();
}
this code sometimes thrown exception
Caused by: java.io.IOException: Stream closed
at sun.nio.cs.StreamEncoder.ensureOpen(StreamEncoder.java:26)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:99)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:116)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:203)
at java.io.Writer.write(Writer.java:140)
at java.io.Writer.append(Writer.java:210)
how I can safely close stream? Because with fileProcessor.close(); now probably I close this stream but there are still some thread which use it.
use thread.join() for all threads in fileProcessor. so that it will wait until all threads finish their task.
client.start();
client.join(); // this will make sure client thread finished before proceed to next step
Link to simple tutorial on thread.join for clear understanding
Don't start a new thread in your process() method, run the functionality synchronously instead.
Alternatively call your close() method from within your process() method.

Categories

Resources