I am working on a relatively simple DB manager, that takes in a number of files, parses and catalogs the information in a particular fashion. I also wrote a simple GUI in Swing for this purpose. In order to speed up the process I want to implement multithreading to the parallelizable parts of the execution in order to speed up the program.
The below code sits in a class called FDBCreatePanel, a custom JPanel, that sits in a FDBManagerFrame which accommodates the main method.
private void dbCreateActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dbCreateActionButtonActionPerformed
jfc = new JFileChooser();
jfc.setVisible(true);
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = jfc.showSaveDialog(null);
((FDBManagerFrame) SwingUtilities.getRoot(this)).startProcessAnimation();
if(returnVal == JFileChooser.APPROVE_OPTION) {
new SwingWorker<Void,Void>(){
#Override
protected Void doInBackground() throws Exception {
File dir = jfc.getSelectedFile();
DbManager dbm = new DbManager(dir, dbNameField.getText());
try{
dbm.doTimeConsumingStuff();
} catch (SQLException e){
// errorhandling
}
#Override
protected void done() {
((FDBManagerFrame) SwingUtilities.getRoot(FDBCreatePanel.this)).endProcessAnimation();
}
}.execute();
}
}
The time consuming method in DbManager class leads to (among others) the following bits of code in the ParserType1 class:
private void init() {
try {
this.reader = new LineNumberReader(new FileReader(this.datfile));
Thread t = new Thread(new Runnable(){
#Override
public void run() {
Entry e;
while((e = parseNextEntry()) != null)
queue.offer(e);
}
}, "t1-parser-thread");
t.run();
} catch (FileNotFoundException e) {
// error handling
}
}
I do not see any t1-parser-thread(s) in JVisualVM when I monitor the execution of my program. It appears as if my code executes entirely on a single thread, ignoring the initiation of new threads. Am I missing something with respect to threading and Swing?
You're calling run() on the newly created Thread object in ParserType1.init(). That doesn't start a new thread - it just execute's the thread's run() method in the existing thread. You should be calling start() instead.
Fundamentally I think it was a mistake for Thread to implement Runnable at all - the distinction between "this is the code that should be executed" (Runnable) and "this is the way I'm going to execute it" (Thread) has been unfortunately blurred. The fact that Thread can also compose a Runnable makes it even worse.
Runnable runnable = new Runnable() { ... };
Thread thread = new Thread(runnable) {
// Override run here...
};
Unless your overridden run method calls super.run(), the Runnable passed into the constructor is ignored. Crazy stuff. Thread should (IMO) be final, not implement Runnable, and force you to provide a Runnable at construction. It's far too late to change now, unfortunately :(
Basically, you should never be calling run() on a Thread. At least, I can't remember the last time I saw that without it being a bug.
As Jon Pointed out you want to call the start() method to actually spawn a new Thread which will call the run method of your inline Runnable. If you just call run it is like you called any other method and it will execute in the same Thread.
}, "t1-parser-thread");
t.start();
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
Related
Java is not my mother tongue and I've been fighting with this problem for a little while.
Basically, I am finding a behavioural difference between calling method switchApplets() directly from init(), and calling it from within a new thread spawned by init().
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser. If called at the end of init(), the new UI renders immediately without any input from the user. But that's not an option because it doesn't wait for the thread to finish its prep work.
Trimmed-down code:
public class PreLoader extends Applet implements AppletStub {
static JProgressBar pBar = null;
static JLabel message;
public void switchApplets() {
try {
Class main_class = Class.forName("MainClass");
Applet main_applet = (Applet)main_class.newInstance();
removeAll();
setSize(0,0);
setLayout(new GridLayout(1,0));
add(main_applet);
main_applet.init();
main_applet.start();
main_applet.setStub(this);
}
catch (Exception e) {
}
}
public void init() {
pBar = new JProgressBar(0, 100);
pBar.setValue(0);
pBar.setStringPainted(true);
message = new JLabel("Beginning work!");
add(message);
add(pBar);
FlowLayout flow = new FlowLayout();
setLayout(flow);
Thread t = new Thread ( new Runnable () {
public void run ()
{
longRunningFunction1();
longRunningFunction2();
message.setText("Work complete! Stand by..");
switchApplets(); //does NOT work as intended from here
return;
}
} );
t.start();
//switchApplets(); //works as intended if called HERE
}
public void longRunningFunction1() {
//perform some tasks, advance progress bar
}
public void longRunningFunction2() {
//perform some tasks, advance progress bar
}
public void start() {
return;
}
public void appletResize(int width, int height) {
return;
}
}
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating. Also tried playing with SwingUtilities' invokeLater/invokeAndWait, but even though switchApplets() gets run on the EDT, it seems that it MUST be called directly from init() (or at least the thread init is running on) to have the desired effect.
Why does calling switchApplets() from within a new thread result in a slightly different (and unwanted) UI behaviour?
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser.
It's likely a deadlock caused by trying to do UI code on the wrong thread.
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating.
You're on the right track. You need to call switchApplets() only from the EDT, and only after the work is done on the other thread.
Are you sure you tried using invokeLater() or invokeAndWait() from within the spawned thread after the long running functions were done? It's been a long while since I did applets but I'm not aware of any applet-specific reason why it wouldn't work, and it would work in any other case. I.e.,
public void run()
{
longRunningFunction1();
longRunningFunction2();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
message.setText("Work complete! Stand by..");
switchApplets();
}
});
}
However, the most proper way to do this is with a SwingWorker rather than a manually created thread. SwingWorker (which is not nearly as well-known as it should be) is designed exactly for the goal of performing background tasks on a separate thread while still being able to update the GUI with progress updates and the results. E.g.,
new SwingWorker<Void,Void>() {
#Override
protected Void doInBackground() { // is called on a background thread
longRunningFunction1();
longRunningFunction2();
return null;
}
#Override
protected void done() { // is called on the Swing thread
message.setText("Work complete! Stand by..");
switchApplets();
}
}.execute();
The Void stuff is because SwingWorker is also capable of returning results and sending intermediate progress updates, but this example doesn't use those features.
You indicated that your long running functions are also updating a progress bar. That's another thing that should happen only on the Swing thread. In practice you can often get away without it, but it's dodgy. Your progress updates can use one of the SwingUtilities.invoke methods, or the mechanisms of SwingWorker; either should work. (SwingWorker itself provides two different ways to do it: Call addPropertyChangeListener (Swing thread) and setProgress (background thread), or call publish (background thread) and override process (Swing thread).)
Also, a small suggestion: if it's inconvenient to deal with a checked exception (or impossible to usefully do so), rather than catching and ignoring it, you should at least catch & rethrow it as an unchecked exception:
catch (Exception e) {
throw new RuntimeException(e);
}
That way, the stacktrace and error message of any exception will not be lost.
Code:
public void doSomethingOrThrowUncheckedException()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
myObject.doSomething()
} catch(CheckedException e) {
new UncheckedException ();
}
}
});
worker.start();
}
Explanation
I want to perform some work in another thread that can throw a checked exception.
I cannot wait for this work to finish and I want the method caller to know if something went wrong with this work since the new thread is not able to handle the exception properly.
Is there a mechanism I can use?
Can you create a Observable outside of the thread? If something goes wrong, the thread sets a value to change that Observable. The main code is an Observer and reacts to the change when the property listener is called.
It depends on what you mean by the caller knowing that something went wrong. A couple of options come to mind immediately.
The worker thread can set an error flag. The disadvantage is that the calling thread will need to check the flag to know that something went wrong. (There can also be a flag for success; as long as neither is set, the calling thread knows that the worker is still working.
The worker thread can call an error method. The disadvantage is that the call will take place in the worker thread. On the other hand, this provides a place to take positive action. The Observer pattern might be useful here (although I think Java's implementation is terrible).
If, when the worker thread completes successfully it communicates the success to Foo, or produces an object that Foo consumes, then expand that mechanism to allow it to pass the checked exception along to Foo, rather than passing the exception to the method calling thread.
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
foo.processResult(result);
} catch(CheckedException e) {
foo.processException(e);
}
}
});
worker.start();
}
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
resultQueue.add(result);
} catch(CheckedException e) {
resultQueue.add(e);
}
}
});
worker.start();
}
If doSomething() doesn't interact with anything when it successfully completes then you'll need to follow one of the other answers.
You may also want to have a look at uncaughtExceptionhandler.
I have checked different questions in this and in other forums, but I didn't find the solution to my problem.
I have an application which runs ffmpeg and exiftool processes. I have concurrency probles, and I would like to control them, using Thread. This is how I built it:
ExiftoolThread
public class ExiftoolThread extends Thread{
String file;
public ExiftoolThread(String file){
this.file = file;
}
public void run(){
serviceToExiftool(file);//Create metadata file
}
}
FfmpegThread
public class FfmpegThread extends Thread{
String itemName;
public FfmpegThread(String itemName){
this.itemName = itemName;
}
public void run(){
serviceFFmpeg(itemName);//Create thumbnai froma video
}
}
Main call
Thread exiftoolThread = new ExiftoolThread(file.getName());
exiftoolThread.run();
try {
exiftoolThread.join(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.write("JSON file created.It contains the metadata. ");
Thread ffmpegThread = new FfmpegThread(itemName);
ffmpegThread.run();
try {
ffmpegThread.join(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.write("Thumbnail created successfully. ");
After this call finishes, there are more actions working with the results of these processes, and there is always one of them which is missed. I guess that's because one of them (exiftool or ffmpeg) finishes earlier and then the process continue before the other finishes.
I am using ffmpegThread.join(3000); to skip this problem, as the documentation says, this method waits untill the thread is died. What am I missing?
Thanks in advance
You need to call Thread.start() instead of Thread.run() on your two threads. The start() method actually spins a new thread to execute code concurrently, while the run() method is a normal method that executes in the calling thread like any other.
additionally, you can improve your thread synchronization setup by replacing the join() calls by use of a java.util.concurrent.CountDownLatch. Your main code will look like this:
CountDownLatch latch = new CountDownLatch(2);
Thread ffmpegThread = new FfmpegThread(itemName, latch);
Thread exifToolThread = new ExifToolThread(itemName, latch);
ffmpegThread.start();
exifToolThread.start();
latch.await(); // With optional timeout
Your two helper threads must both call latch.countDown() when they're done.
You have to call start() to run the code in the new thread. Also, join() block the current thread, so you have to call it after you start all your thread.
I have an application the leans heavily on map functionality. From the first Activity I call the runOnFirstFix() method to load a lot of data from a database once the location of the user has been found, but I also want to be able to interrupt this runnable and stop it mid execution for when I switch activity or the user presses the button to stop it running.
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
loadMapData(); //Here the method is called for heavy data retrieval
}
});
How can I stop this Runnable mid execution?
You could (and probably should) use an AsyncTask
private class MapLoader extends AsyncTask<Void, Void, Data> {
#Override
protected Data doInBackground(Void... params) {
return loadMapData(); //Here the method is called for heavy data retrieval, make it return that Data
}
#Override
protected void onPostExecute(Data result) {
//do things with your mapview using the loaded Data (this is executed by the uithread)
}
}
and then in replace your other code with
final MapLoader mapLoader = new MapLoader();
myLocationOverlay.runOnFirstFix(new Runnable() {
public void run() {
mc.animateTo(myLocationOverlay.getMyLocation());
mc.setZoom(15);
userLatitude = myLocationOverlay.getMyLocation().getLatitudeE6();
userLongitude = myLocationOverlay.getMyLocation().getLongitudeE6();
userLocationAcquired = true;
mapLoader.execute();
}
});
then you should be able to cancel the running task when you no longer want it to complete using
mapLoader.cancel(true);
I hope the code compiles, I haven't tested it, but it should work :)
Just make sure that it is the ui thread that creates the MapLoader
edit: I think you need to wrap the mapLoader.execute(); call in a runOnUiThread() call in order for it to work correctly since runOnFirstFix() might spawn a new thread
use the handler object to handle this runnable.
define this runnable with the runnable object.
after that in handler you can start the cancel this runnable service
for e.g.
Handler handler = new Handler();
on startCommand()
handler.postDelayed(myRunnable,5000);
this will execute the run method of runnable after 5 sec
for cancel
handler.removeCallbacks(myRunnable);
and your runnable define like this way
private Runnable myRunnable = new Runnable(){
public void run(){
// do something here
}
}
http://developer.android.com/reference/android/os/Handler.html
http://developer.android.com/reference/java/util/logging/Handler.html
http://www.vogella.de/articles/AndroidPerformance/article.html
In Java, you can call interrupt() on a running thread which should stop the execution of given thread. But if any kind of blocking operation like wait() or join() is being performed, InterruptedException will be thrown. Even some kinds of socket-related blocking operations can lead to InterruptedIOException under Linux, or under Windows the operation still remains blocked (since Windows does not support interruptible I/O). I think you still could interrupt your runnable, just be aware that some I/O may not be interrupted until finished and if blocking, it might throw those kind of exceptions I mentioned.
I have an event handling mechanism in my Android code to dump the sensor values in a file. Right now, I'm doing it in the main UI thread and hence the UI button responsiveness is very sluggish and I would like to speed it up.
How can I use multithreading on event handling functions? I'm trying to do it like this:
Create a global variable writeNow.
When the sensor value changes, set WriteNow = true
Create a thread in the class which looks like this:
Thread thread1 = new Thread()
{
public void run()
{
if(writeNow == true)
{
try
{
fos.write(s.getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
writeNow = false;
}
}
};
Thus, whenever writeNow is true, it will write to a File and then set WriteNow to false. However, I realize this is not the right approach, because the thread will execute once and then stop executing. When I tried a simple example with a while(true) and wait(), I found that the thread is interrupted millions of times.
So how do I enclose this event handling mechanism in a single thread, for speeding up a process?
Thanks!
You can try one of the following approaches:
It looks like you're trying to keep your writer thread running all the time; what you can do is spawn the thread only when you need it. Take a look at the example in the Android documentation for handling expensive operation in the UI thread.
Here is the example from that page:
public class MyActivity extends Activity {
[ . . . ]
// Need handler for callbacks to the UI thread
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateResultsInUi();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[ . . . ]
}
protected void startLongRunningOperation() {
// Fire off a thread to do some work that we shouldn't do directly in the UI thread
Thread t = new Thread() {
public void run() {
mResults = doSomethingExpensive();
mHandler.post(mUpdateResults);
}
};
t.start();
}
private void updateResultsInUi() {
// Back in the UI thread -- update our UI elements based on the data in mResults
[ . . . ]
}
}
Since it doesn't look like you're doing anything in the UI thread once you finish writing you don't really need to bother with a Handler. But you might want to use it to display a Toast once the file has been written to.
On the other hand, if you still want to have a thread running, you might have it sleep() and periodically wake up and check the status of writeNow.
Thread thread1 = new Thread()
{
public void run()
{
while(true)
{
if(writeNow == true)
{
try
{
fos.write(s.getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
writeNow = false;
}
try
{
Thread.sleep(100); //sleep for 100 ms
}
catch (InterruptedException e)
{
Log.d('', e.getMessage());
}
}
}
};
Note that this will quickly get complicated and you might lose the bytes you want to write if your thread is sleeping when new data comes in and when it wakes up, even newer data has been received and has overwritten the previous bytes. You'd need some sort of a queue to manage that.
I'm not sure what you were doing with the wait() but that should've also worked and is in fact, the approach for problems involving a consumer and producer. The idea is to have your thread synchronize and wait() on a shared object (like perhaps your queue of bytes); a second thread will call notify() on the shared object when there is data available to write and the writer thread will be woken up. The writer thread should then write and reloop. Take a look at this tutorial.
As for the interruption of your thread, your thread may be interrupted for a number of reasons which is why it is good practice (especially when using wait()) to ensure that the condition you checked before you called wait() is still valid because you could've been woken because of either a call to notify()/notifyAll() or because of an interruption.
Handler handler = null;
handler = new Handler();
//create another class for and make consrtuctor as u want. so that u can use that effectively.
//for example.
popupIndex = new IndexThread(handler,head, target,ltp,price,IndexNifty.this,columsView,call);
popupIndex.setColumnViewexit(columsView);
handler.postDelayed(popupIndex, 300);
//another class
public IntraThread(Handler handler,String script,int target,int ltp,int price,Intraday intraday,TextView columsView,String call){
super();
this.target = target;
this.ltp = ltp;
this.price = price;
this.intraday = intraday;
this.columsView = columsView;
this.script= script;
this.handler= handler;
this.call= call;
}
public void run(){
// write ur code here....
}