Managing thread from a mouseclick - java

May be it is a basic question. But I'm a little confused about it. In my design I've a thread that is started from a mouse click. Method looks something like this:
Runnable r = new Runnable(){
public void run(){
A.firstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
}
};
new Thread(r).start();
Here B.FirstMethod(), B.SecondMethod(), B.ThirdMethod(); are accessing same variables and do some database operations during execution (i.e. locking, reading, writing etc.). But, If mouse is clicked during the execution or before finishing all the tasks I often get error message from database. How can I handle such type of situations. Here I cannot force the user to wait just with a simple Progressbar.

To handle such situation, you can disable the button once the thread has started its execution, and enable it again once the thread is going to finish its execution.
The code will then look like following:
Runnable r = new Runnable()
{
public void run()
{
button.setEnabled(false);
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
button.setEnabled(true);
}
};
new Thread(r).start();
Or when the button is clicked, you can use a boolean variable to check if the thread is in progress or not, and then decide as to what needs to be done like:
volatile boolean inProgress = false; // Instance Variable
Runnable r = new Runnable()
{
public void run()
{
inProgress = true;
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
inProgress = false;
}
};
if(!inProgress)
new Thread(r).start();
else
Popup some message perhaps

Related

Thread is blocking execution

I have a simple class which has a thread in it. Whenever user clicks on a button, I want to run the thread. Everything works great, except that whenever I click on the button while the thread is already running, my onTouch executes only after the thread has finished executing.
..
MyTouchAnimatorClass touchAnimatorClass = new MyTouchAnimatorClass();
view.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick( View view )
{
touchAnimatorClass.onTouch();
}
});
..
And my class with the thread:
Class MyTouchAnimatorClass
{
private boolean threadRunning = false;
public void onTouch() // <-- only executes AFTER the thread is complete
{
if( !threadRunning )
animate();
}
private void animate()
{
threadRunning = true;
Runnable r = new Runnable()
{
#Override
public void run()
{
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
int i=0;
boolean doBreak = false;
while( true )
{
i+=1;
if( i == 100 )
break;
}
}
}
}
}
new Thread( r ).start();
threadRunning = false;
}
}
I can't understand why this is happening, isn't the Runnable running in its own thread? Any suggestions please? Thank you!
EDIT:
I tried using
new Thread( r ).start();
Instead of:
r.run();
But unfortunately the same problem persists:
If I click the button the second time (while the thread is still running from the first click), it should execute onTouch, but shouldn't execute animate() since it is still running from the previous click.
What actually happens: The touch is non response until the thread from the first click has finished executing. Then onTouch triggers (even though I pressed it few seconds ago) and a new thread is started again.
If I press the button 10 times quickly, it will do 10 loops in a row, instead of doing one and blocking the others.
activity.runOnUiThread is asking the Android system to run this Runnable on the UI thread.
You can rather do new Thread(r).start();
Like this:
private void animate()
{
threadRunning = true;
//Define the work as a Runnable
Runnable r = new Runnable()
{
#Override
public void run()
{
int i=0;
//boolean doBreak = false; //Not used
while( true )
{
i+=1;
if( i == 100 )
break;
}
threadRunning = false; //Just before leaving
}
}
//Give that work to a new thread and start the thread
new Thread(r).run();
}
Runnable isn't a thread, is just a set of instructions to be executed in a thread
in order to achieve what you want you need to do
new Thread(r).start(); at end of your code

Update jProgressBar from another thread

I'm new in java. I'm trying to understand thraeads and timers in java. It was big problem for me to undate ProgressBar from another thread. I read many posts and found answers. So can you say is this the best way to resolw my task. So, what I want is to run second thread and when it's done, stop progress bar and change text on the button. So I creat Frame with button and progress bar in Test class:
After I realize action listener for Button to run second thread:
public class Test extends javax.swing.JFrame {
RunBg thread = new RunBg();
....
// declaration for button, progressbar and main() method
....
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
// needed to check is the thread running at first time else creat new object and rund hread again cause thread can be executed once
if(thread == null){
thread = new RunBg();
}
if (jProgressBar1.isIndeterminate()) {
jProgressBar1.setIndeterminate(false);
jButton1.setText("Run!");
thread.suspend();
} else {
jButton1.setText("Working...");
jProgressBar1.setIndeterminate(true);
// let us know is the second thread running or nope so we can know resume it or pause
if (thread.isAlive()) {
thread.resume();
} else {
thread.start();
}
timer.start();
}
}
/*
Then I creat timer to know is my thread still alive else change Progress bar and button
*/
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(!thread.isAlive()){
thread.stop();
jProgressBar1.setIndeterminate(false);
jButton1.setText("Запустить!");
timer.stop();
// thread.interrupt();
thread = null;
}
}
});
...
// end of class
}
And my second class for another thread named RunBG:
public class RunBg extends Thread{
int i = 0;
public void run(){
while(i<20000){
System.out.println(">>>"+i);
i++;
}
System.out.println("<<<Finished>>>");
}
}
Everythig works fine , but I have question. Is there a better way to realize my task or maybe I made some mistakes. Also I thik that my code will help another beginners who looking for help to understand how it's work.

How to cycle through background colors in Android / Java?

I have a list of hex colors with a duration in milliseconds for each one. I would like to fill the screen with each color for its duration, then move on to the next color.
I tried to iterate over the colors to do the following:
myView.setBackgroundColor(Color.parseColor( theColor ));
SystemClock.sleep( theDuration );
myView.setBackgroundColor(Color.parseColor( nextColor ));
SystemClock.sleep( nextDuration );
etc...
which seemed obvious to me but doesn't do anything to the view when it's running, at least in my AVD. I'm learning that it's because Android only draws at predefined times. (I tried calling "Invalidate()" as well with no luck.)
What is the best way to display all the colors consecutively?
(I realize I shouldn't be calling sleep() either, so any suggestions for that would also be appreciated.)
Thanks.
new Thread() {
#Override
public void run() {
YourActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
myView.setBackgroundColor(Color.parseColor( theColor ));
}
Thread.sleep( theDuration);
YourActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
myView.setBackgroundColor(Color.parseColor( nextColor ));
}
Thread.sleep( nextDuration );
}
}.start();
Put this in a method and call it.
There are many ways to achieve what you want. One could be to use Handler and Runnable. Assuming you know how to get current color and duration, you could do:
declare Runnable as class variable
private Runnable runnable = null;
inside onCreate(), after you set initial view, initialise Handler
final Handler handler = new Handler();
initialise runnable and change the background in run() method
runnable = new Runnable() {
#Override
public void run() {
//change the color
myView.setBackgroundColor(currentColor);
//run it again in nextDuration miliseconds
handler.postDelayed(toggle, nextDuration);
}
};
//start runnable in theDuration miliseconds
handler.postDelayed(toggle, theDuration);
You could have arrays of colors and durations and cycle through them with index variable. This is assuming that myView is a valid view.
EDIT:
To those who downvoted, read the documentation for Handler:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it...
In other words, you are creating a handler in onCreate() of your activity, so it will be able to update your view.
This blogpost from adroid-developers website uses very similar construct as proposed above.
The Handler runs the update code as a part of your main thread, avoiding the overhead of a second thread and also making for easy access to the View hierarchy used for the user interface.
See here and here answered by CommonsWare and here - answered by Laith Alnagem.
I ended up creating a Runnable inside the my button click event handler. Everything (looping through the colors and durations plus "sleeping" based on the durations) is done in the Runnable run() method.
public void playOnClick(View v) {
Runnable runnable = new Runnable() {
public void run() {
...
}
Then I created a handler inside my UI Activity class that just changes the color of the background.
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
String theColor = b.getString("color");
myView = (View) findViewById(R.id.bigView);
myView.setBackgroundColor(Color.parseColor(theColor));
}
};
Inside the run() method, he Runnable sends a message to the handler containing the background color using Bundle/Message objects:
b = new Bundle();
b.putString("color", theColor);
msg = new Message();
msg.setData(b);
handler.sendMessage(msg);

Getting and Setting a Flag variable in a thread

I am interfacing with a JNI that allows me to use a fingerprint scanner. The code I have written takes the scanned ByteBuffer parsed back to it by the JNI and turns it into a BufferedImage for saving.
What I can't figure out is how to wait for the scan thread to finish before the the jlabel icon on my GUI tries to update. What would be the easiest way to do this?
What else do I need to add?
Edit:
//Scanner class
Thread thread = new Thread() {
public void run() {
// [...] get ByteBuffer and Create Image code
try {
File out = new File("C:\\Users\\Desktop\\print.png");
ImageIO.write(padded, "png", out);
// [???] set flag here
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
return true;
//Gui class
private void btnScanPrintActionPerformed(java.awt.event.ActionEvent evt) {
Scanner scanPrint = new Scanner();
boolean x = scanPrint.initDevice();
//Wait for the scanning thread to finish the Update the jLabel here to show
//the fingerprint
}
Not sure if you are using Swing or Android for UI but you would want to notify the main event dispatch thread (in swing it is called just that). You would run the scanning thread, then when complete send a 'message' to the EDT with the action that you want to be done to the button.
Thread thread = new Thread(new Runnable(){
public void run(){
//scan
SwingUtiltilies.invokeLater(new Runnable(){
//here you can update the the jlabel icon
public void run(){
jlabel.setText("Completed");
}
});
}
});
In UI development there is no waiting for an action to complete because you always want the EDT to be responsive.
at the end of a the scan thread, use SwingUtilities.invokeLater() to update the gui with the results of the scan.

Java and SWT: Threads and Listeners

I'm actually new to Java and SWT, so my question might sound dumb.
I've looked over the intrnet (and stackoverflow) but all the answers and examples are too complex for a noob like me.
I have a class, call it Admin. When I click a button, it launches a method in another class(Handler).
In Admin I have a progress bar, that should increase with the
operation in Handler.
I don't know how much time the operations in
Handler takes, but I know I have 9 of them.
I would like, somehow,
to inform Admin when each method has finished.
What I have so far: (non relevant parts omitted)
Admin.java:
ProgressBar bar = new ProgressBar(this, SWT.SMOOTH);
Button btn = new Button(this, SWT.NONE);
btn.setText("Update");
btn.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
btn.setEnabled(false);
thread.start();
}
});
Handler handler = new Handler();
final Thread thread = new Thread(){
public void run() {
handler.run();
for(int i=0; i<=10; i++) {
final int value = i;
try {
Thread.sleep(800);
} catch (Exception e) { }
display.asyncExec(new Runnable(){
public void run() {
bar.setSelection(value);
}
});
}
}
};
Handler.java:
public class Handler implements Runnable{
void m1() {...}
void m2() {...}
...
void m9() {...}
public void run()
{
m1();
m2();
...
m9();
}
With this implementation, the call to handler.run() works fine, and the progress bar is filling, but of course they are not "corelated" in any way.
I will appreciate your wisdom!
Thank you very much!
The highly coupled way of solving this, is to have the Handler take a ProgressBar as input in the constructor, and after m1() finishes, it updates the progress to 1/9 and so on. A better (more decoupled) way to do it, is that you can "listen" to Handler, and that Handler fires an event with its progress after each method finishes. Then you can update in the Admin.java.
I will ask you to consider using ProgressMonitorDialog from JFace if adding this library to your application is not much of a problem. Your code then would look something like below:
ProgressMonitorDialog dialog = new ProgressMonitorDialog(parent);
dialog.run(true, true, new IRunnableWithProgress() {
#Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
monitor.beginTask("my work", 9);
m1();
monitor.worked(1);
m2();
monitor.worked(1);
...
m9();
monitor.done;
}
});
You can also send the monitor instance into your m* methods for even detailed reporting. Have a look at SubProgressMonitor for dividing each one of your initial 9 ticks further before sending them into each m* method.
But this means that your progress bar is a new dialog which might not be acceptable to you so in that case the first answer suits your needs.

Categories

Resources