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.
Related
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.
I have a simple application in which I create 3 threads inside a class to ping 3 different websites and note the time taken to do so.
I wish to enhance it by seeing which thread out of the 3 executes successfully first and terminating the other two .
Which class of the JDK would be helpful in doing so ? and how ?
Sample code to ping websites :
public static boolean pingUrl(final String address) {
try {
final URL url = new URL("http://" + address);
final HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
urlConn.setConnectTimeout(1000 * 10); // mTimeout is in seconds
final long startTime = System.currentTimeMillis();
urlConn.connect();
final long endTime = System.currentTimeMillis();
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
System.out.println("Time (ms) : " + (endTime - startTime));
System.out.println("Ping to "+address +" was success");
return true;
}
} catch (final MalformedURLException e1) {
e1.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
return false;
}
I wish to enhance it by seeing which thread out of the 3 executes successfully first and terminating the other two .
I would use an ExecutorService combined with a ExecutorCompletionService. Then, when the first Future is returned from the completion service when the first task completes, you would call shutdownNow() on the ExecutorService.
The javadocs for ExecutorCompletionService are pretty good and show how to use it.
// maybe you want 10 threads working on your tasks
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(threadPool);
for (Callable<Result> task : tasks) {
// submit your tasks to the completion service, they run in the thread-pool
ecs.submit(task);
}
// once you get one result
Future<Result> future = ecs.take();
// kill the rest of the tasks
threadPool.shutdownNow();
Result result = future.get();
// probably will need to close the thread connections, see below
// maybe call threadPool.awaitShutdown(...) here to wait for the others to die
The only problem with this mechanism is that this will only interrupt the threads. In your case they are going to be stuck in urlConn.connect(); which is not interruptible. Once the ecs.take() returns, you are going to have to run back over your tasks and call disconnect() on the the HttpURLConnection that are still in progress. Even then I'm not sure if it will stop a connection that is currently underway. If that doesn't work then you may need to switch to using Apache HttpClient or some other class that you can close to stop the threads from waiting longer.
for (Callable<Result> task : tasks) {
// you'll need to do something like this
task.closeConnection();
}
In your case, your task might look something like:
public class MyPingTask implements Callable<Boolean> {
private String address;
public MyPingTask(String address) {
this.address = address;
}
public Boolean call() throws Exception {
// obviously the pingUrl code could go right here
return pingUrl(address);
}
}
Here is the Java tutorial on ExecutorService and related classes.
I suppose BlockingQueue may be useful. The main idea that spawned thread writes some value to BlockingQueue when finished and gracefully closes on InterruptedException
For example:
public void runPing(List<String> urls) {
Collection<Thread> runningThreads = new ArrayList<>(urls.size());
final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(urls.size());
for (int i = 0; i < 3; i++) {
final String url = urls.get(i);
Thread t = new Thread(new Runnable() {
public void run() {
pingUrl(url);
queue.add(1);
}
});
runningThreads.add(t);
}
try {
queue.poll(1, TimeUnit.HOURS);
interruptChilds(runningThreads);
} catch (Exception e) {
interruptChilds(runningThreads);
}
}
private void interruptChilds(Collection<Thread> runningThreads) {
for (Thread t : runningThreads) {
t.interrupt();
}
}
Please note that in there are no handling of InterruptedException. It should be added in your method
So I have a thread, which I previously could not get running but that's now been solved thanks to a member on this site, that question can be found here.
To stop my thread I created a boolean in the thread class and set it to false, if it is set to true then the thread should stop. I even check when I am stopping the thread by printing the thread but it prints true (which it should) but the thread keeps on running.
My thread (CheckFiles.java) class looks like this.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
class CheckFiles extends Thread {
static boolean stop = false;
public void run() {
while (!stop) {
System.out.println("Thread " + stop);
try {
String line;
BufferedReader b = new BufferedReader(new FileReader(UserInterface.location));
while((line = b.readLine()) != null) {
Ststem.out.println(line);
}
} catch (IOException e) { System.out.println(e); }
}
}
}
To stop the thread I have a button and the code of it looks like this.
stopChecking.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
CheckFiles.stop = true;
System.out.println(CheckFiles.stop); //Prints true when pressed
}
});
Why is my thread not stopping, or is there a better way to do it?
EDIT: When I try interrupting the thread I get the syntax error
Cannot make a static reference to the non-static method interrupt() from the type Thread
Also when I make the boolean stop volatile the thread is still running.
The thread is blocking on b.readLine() as that line of code causes thread execution to halt until there is some input available.
To "force" stop, use Thread.interrupt()
E.g:
stopChecking.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
//To clarify the following uses a INSTANCE of CheckFiles, called CheckFiles.
//In other words, somewhere there was a declaration with the format:
// CheckFiles CheckFiles = ...
CheckFiles.stop = true;
CheckFiles.interrupt(); //Or whatever the name of your thread instance is
System.out.println(CheckFiles.stop); //Prints true when pressed
}
});
The internal reading loop should also be modified as such:
while(!stop && (line = b.readLine()) != null){
Ststem.out.println(line);
}
As the interrupt merely unblocks the I/O, we need to check if stop is still false before we proceed to do another blocking read.
As others have suggested, an alternative way is to directly invoke b.close() after setting stop = true;.
Edit:
Like Vakh has said, you should also make your boolean volatile so that updates to the stop variable are immediately visible to all threads.
You must declare stop as volatile:
static volatile boolean stop = false;
Basically, volatile implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value, which seems to occur in your case where the compiler assumes that the stop value is always false in your thread since it never writes an other value for it.
When you stop the bufferedreader with b.close(), wouldn't that stop the thread?
Use the threads interruption flag for termination:
public class FileChecker implements Callable<Void> {
private final File location;
public FileChecker(File location) {
this.location = location;
}
#Override
public Void call() throws Exception {
try {
while (!Thread.currentThread().isInterrupted()) {
try (BufferedReader b = new BufferedReader(new FileReader(location))) {
String line;
while ((line = b.readLine()) != null) {
if (Thread.interrupted()) {
throw new InterruptedException();
}
System.out.println(line);
}
}
}
} catch (InterruptedException ex) {
// restore interruption flag
Thread.currentThread().interrupt();
}
return null;
}
}
You can now schedule your file checker using an ExecutorService:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new FileChecker(...));
Stop the file checker by either cancelling the Future or shutting down the executor:
future.cancel(true);
executor.shutdownNow();
I'm implementing a GUI for a console application, and I need to do some actions (for example, parse an XML file) in a specified time interval. I decided to use javax.swing.Timer alongside SwingWorker to be sure that these actions will not make my application unresponsive.
I had implemented the timer this way:
public class DataUpdateTimer extends Timer {
private String dataFlowControllerXML = null;
private DataUpdateWorker dataUpdateWorker = null;
public class DataUpdateWorker extends SwingWorker {
private String dataFlowControllerXML = null;
DataUpdateWorker(String dataFlowControllerXML) {
super();
this.dataFlowControllerXML = dataFlowControllerXML;
}
#Override
protected Boolean doInBackground() throws Exception {
Thread.sleep(300);
return Boolean.TRUE;
}
}
public class DataUpdateIntervalListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
DataUpdateTimer timer = (DataUpdateTimer)e.getSource();
DataUpdateWorker dataUpdateWorker = timer.getDataUpdateWorker();
if (dataUpdateWorker != null)
if (dataUpdateWorker.isDone()) {
Boolean updateResult = Boolean.FALSE;
try {
updateResult = (Boolean)dataUpdateWorker.get();
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
}
dataUpdateWorker = null;
}
// Creating new worker thread here
if (dataUpdateWorker == null) {
timer.dataUpdateWorker = new DataUpdateWorker(timer.dataFlowControllerXML);
// Starting a new worker thread for parsing Data Flow Controller's XML
timer.dataUpdateWorker.execute();
return;
}
}
}
DataUpdateTimer(Integer dataUpdateInterval, String dataFlowControllerXML) {
super(dataUpdateInterval.intValue(), null);
this.dataFlowControllerXML = dataFlowControllerXML;
addActionListener(new DataUpdateIntervalListener());
}
#Override
public void stop() {
super.stop();
if (dataUpdateWorker != null) {
if (!dataUpdateWorker.isDone() || !dataUpdateWorker.isCancelled())
dataUpdateWorker.cancel(true);
}
}
}
...and use it as follows:
new DataUpdateTimer(1000, dataFlowControllerXML).start();
Everything works as I wish. Timer creates new a SwingWorker instance and executes it. After the worker is done, the new one is created and executed.
The thing I'm confused by is that after the worker's thread is done I still can see it running in Netbeans' debugging window (for example, as SwingWorker-pool-3-thread-1) or in Windows Task Manager (the number of running threads doesn't decrease after the thread is done). The number of SwingWorker threads is limited to 10, but having them running embarrasses me.
In the case of simple thread usage:
Thread th = new Thread(new Runnable() {
public void run() {
int a = 0;
}
});
th.start();
This thread automatically disappears after execution.
Is this SwingWorker behavior normal?
Yes, this is normal. As the thread's name suggests, the swing workers' model (background) actions are being delegated to a thread pool. When the work is done the thread is returned to the pool so another worker can use it. This eliminates some overhead in creating/destroying threads which can be expensive.
By the way, the background threads won't stick around forever. Looking at the source for SwingWorker I see:
//from SwingWorker.java (c) Sun Microsystems/Oracle 2009
executorService =
new ThreadPoolExecutor(1, MAX_WORKER_THREADS,
10L, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
This indicates that the threads will die off after being idle for 10 minutes.
I have a thread in Java which starts a HttpService.
ProcessBuilder pb = new ProceeBuilder(command);
Process process = pb.start();
process.waitFor();
I have another thread which checks if the service is started.
while (result != 0) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
}
}
Now I need to somehow get information about whether the service has failed to start or it's successfully started. I need to get this back to the Main class which started both of these threads in order to proceed. Something like
while (!started || !failed) {
wait for getting information from the threads.
}
What can you advise?
Thank you.
How about using a callback that you pass to both threads?
(omitted try-catches)
public class MyCallback {
private Boolean processSuccess;
private Boolean serviceSuccess;
public synchronized void notifyProcessStart(boolean success) {
this.processSuccess = success;
this.notifyAll();
}
public synchronized void notifyServiceCheck(boolean success) {
this.serviceSuccess = success;
this.notifyAll();
}
public synchronized void waitForResult() {
while(processSuccess == null || serviceSuccess == null) {
this.wait();
}
// ... do something good
}
}
I am very sorry but I am afraid that your code that checks that service is started has bug.
This code is running very quickly, starts server socket and immediately closes it. If you mean that this thread should exit when process is started listening to the same port it is wrong. Your process has 50% of chance to start successfully and other 50% to fail because when it is trying to start listening to the port your watch dog is listening to the same port itself.
So, I believe that you should try to run process using ProcessBulder (exactly as you are doing) and then start delayed watchdog task that tries to connect to this port, i.e.
private boolean isServiceRunning() {
int port = 123;
try {
new Socket("localhost", port).close();
return true;
} catch (IOException e) {
return false;
}
}
This method should be called from separate thread. The best way to implement thread is to use some tool that does it for you. In this case java.util.Timer is the best choice. I am suggesting to run periodic task that will call our method isServiceRunning() and cancel itself if result is true:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
if(isServiceRunning()) {
this.cancel();
}
}
}, new Date(), 10000);
But if this solution is not good for you I'd suggest you to implement interthread communication using wait() and notfify(). Do not forget that both must be in synchronized block.
Good luck!
You can try using boolean flags. Adapting your example code:
Thread 1:
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
process.waitFor();
if(!wasConnectionEstablished()) {
setConnectionFailed(true);
}
Thread 2:
while ((result != 0) && (!isConnectionFailed())) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
wait(timeout);
}
}
if(isConnectionFailed())
throw new ConnectionFailedException();
else setConnectionEstablished(true);
//continue normal execution