I have a Button in my android app which must run a continuous action while holding it down, for that I created an onTouchListener to handle such issue, my structure is when catching ACTION_DOWN event a thread with a while(true) loop runs, then when catching ACTION_UP event that thread stopped via wait() in order to resume it's looping again upon holding down, the problem is that when trying to execute thread.wait() the thread doesn't enter the synchronized block and doesn't wait, but it stops the execution of runOnUIThread which exists in that thread, and after I press any button after that the app crashes and gives me ANR Exception : Input dispatching timed out:
// the thread declaratrion
test = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
// still loops here
value = value + 1;
runOnUiThread(new Runnable() {
public void run() {
// doesn't go here anymore
mTextView.setText(Integer.toString(value));
}
});
// still loops here
synchronized (test) {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
// the onTouchListener
case MotionEvent.ACTION_DOWN:
if (!test.isAlive()) {
synchronized (test) {
test.start();
}
} else {
synchronized (test) {
test.notify();
}
}
break;
case MotionEvent.ACTION_UP:
// accepts the action
synchronized (test) {
try {
// doesn't goes here
test.wait(); // doesn't execute
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
default:
break;
Probably you use too low level API for your needs. Just look at http://developer.android.com/reference/java/util/concurrent/ScheduledExecutorService.html
One thing I see is potential dangerous is that in your separate thread, you are waiting inside a synchronized statement. So when that guy is sleeping, it takes the lock with him, and therefore in your onTouchListener, none could grabbed the lock but to wait. And because the onTouchListener is controlled in the framework, it may stop running if it waits too long. I did a simple test here to prove it.
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
final Object globalLock = new Object();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
System.out.println("thread1 grabbed the lock.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1 returned the lock.");
}
}
});
t1.start();
Thread.sleep(200);
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("thread2 is waiting for the lock...");
synchronized (globalLock) {
System.out.println("thread2 got the lock");
}
}
});
t2.start();
t1.join();
t2.join();
}
}
Related
I am trying to make a program simulating a very simple dishwasher which has three threads. The first thread is responsible for adding water, the second thread for opening the door of the device which should force the adding water thread to wait until the third thread notify(). the system runs but it never stops and the notify() never works.
import java.util.logging.Level;
import java.util.logging.Logger;
public class threadexample {
public static boolean flag = false;
void Open() throws InterruptedException {
synchronized (threadexample.this) {
flag = true;
Thread.sleep(2000);
System.out.println("producer thread paused");
wait();
System.out.println("Resumed");
}
}
void Close() throws InterruptedException {
synchronized (threadexample.this) {
flag = false;
Thread.sleep(6000);
System.out.println("System resuming..");
notifyAll();
Thread.sleep(2000);
}
}
public static void main(String[] args) throws InterruptedException {
threadexample closing = new threadexample();
threadexample openning = new threadexample();
final Door door = new Door();
// Create a thread object that calls pc.produce()
Thread t3 = new Thread(new Runnable() {
#Override
public void run() {
if (flag == false) {
for (int check = 0; check <= 8; check++) {
if (check == 1) {
System.out.println("Adding Water..." + Thread.currentThread().getName());
} else {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(threadexample.class.getName()).log(Level.SEVERE, null, ex);
if (flag == true) {
try {
closing.Close();
} catch (InterruptedException ex1) {
Logger.getLogger(threadexample.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
}
}
}
try {
Thread.sleep(4000);
} catch (InterruptedException ex) {
Logger.getLogger(threadexample.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
openning.Open();
} catch (InterruptedException ex) {
Logger.getLogger(threadexample.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
closing.Close();
} catch (InterruptedException ex) {
Logger.getLogger(threadexample.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
t1.start();
t2.start();
t3.start();
}
}
1) You call wait without checking whether or not the thing you are waiting for has already happened. If you wait for something that has already happened, you will wait forever because notify will not be called again.
2) You call sleep while holding the lock. That doesn't make sense.
3) You have:
threadexample closing = new threadexample();
threadexample openning = new threadexample();
and:
synchronized(threadexample.this)
So you create two instances of threadexample and each thread synchronizes on its own instance of threadexample. That's not right either.
You never actually call openning.Close(), hence openning.notify() is never called. Therefore, Thread t1 waits forever. Mind you, wait() and notify() call the Object's monitor and are not static. You want to use threadexample lock = new threadExample().
i am generating a random string for infinite time and setting it to a EditText.
when i was not using runOnUi app was working on newer devices which have high capability. but it crashes on older model when i start the thread and gave error(called from wrong thread exception)
Then i used runOnUi but it makes the super slow and force close it.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
tryPass.setText(getAlphaNumericString());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
});
thread.start();
You're trying to block UI thread by calling Thread.sleep(2000); on UI thread.
Try this way:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tryPass.setText(getAlphaNumericString());
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
I am running into a minor issue that I don't understand. I have a simple progress bar but Thread.interrupt does not stop the thread. I have to hack it a global variable. I wonder if anyone can stop the issue.
I tried this thread, but did not work for me:
How to stop a thread(progressbar) in android
here's the code with the hacks
// Start lengthy operation in a background thread
calcThread = new Thread
(
new Runnable()
{
public void run()
{
Thread current = Thread.currentThread();
//while (!current.isInterrupted()) // this does not
while (threadLoop) // this hack works
{
doWork();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
Log.d(TAG, "out of thread loop");
}
}
);
calcThread.start();
now where I try to stop the thread
public void onClickAbout(View view)
{
if (view.getId() == R.id.buttonAbout)
{
Log.d(TAG, "onButtonPressed");
calcThread.interrupt(); // This does not work
threadLoop = false; // this works.
}
}
Why do I have to hack a global? In other words, why Thread.interrupt does not stop the thread.
thx!
Why don't you try the following
Thread background = new Thread() {
public void run() {
try{
for(int s=0;s<=100;s++)
{
s=s+20;
sleep(1000);
progressbar.setProgress(s);
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
//do some thing after you finish thread
}
}
};
background.start();
It doesn't work because you're catching InterruptedException and ignoring it. The thread is no longer interrupted after the exception is thrown. (See this Q&A.) But k0sh is right, you should use an AsyncTask.
Thread thread;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_yippi);
final Handler hn=new Handler();
final TextView text=(TextView)findViewById(R.id.TextView01);
final Runnable r = new Runnable()
{
public void run()
{
text.settext("hi");
}
};
thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1750);
hn.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
thread.stop();}
The code here. I can not stop the runnable thread. Also, thread.stop() and thread.destroy() are deprecated. Can somebody help me? And also I don't understand how to stop the thread with the thread.interrupt() method. What's wrong?
The JavaDoc for Thread.stop() lists the following article as explanation for why stop() is deprecated: http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized).
interrupt() is more suitable to stop some Thread from waiting for something, that is probably not coming anymore. If you want to end the thread, it's best to let its run() method return.
Create a boolean variable to stop the thread and use it in while(boolean) instead of while(true).
You can use Thread.interrupt() to trigger the InterruptedException within your thread. I've added code below that demonstrates the behavior. The mainThread is where your code would be and the timer Thread is just used to demonstrate delayed triggering of the interrupt.
public class Test {
public static void main(String[] args) {
final Thread mainThread = new Thread() {
#Override
public void run() {
boolean continueExecution = true;
while (continueExecution) {
try {
sleep(100);
System.out.println("Executing");
} catch (InterruptedException e) {
continueExecution = false;
}
}
}
};
mainThread.start();
Thread timer = new Thread() {
#Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stopping recurring execution");
mainThread.interrupt();
}
};
timer.start();
}
}
You can use interrupt method of Thread to try stop a thread, like below code.
May be it`s useful to you.
public class InterruptThread {
public static void main(String args[]){
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
System.out.println("Thread is Runing......");
sleep(1000);
}
} catch (InterruptedException e) {
// restore interrupted status
System.out.println("Thread is interrupting");
Thread.currentThread().interrupt();
}
}
};
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Will Interrupt thread");
thread.interrupt();
}
}
I have a problem following from my previous problem. I also have the code SwingUtillities.invokeAndWait somewhere else in the code base, but when I remove this the gui does not refresh. If I dont remove it the error I get is:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
at java.awt.EventQueue.invokeAndWait(Unknown Source)
at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)
The code in HumanPlayer.act is:
public Action act(final Action[] availiableActions) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
gui.update(availiableActions);
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
return getActionPerfomed();
}
Image of threads when in debug as screen doesn't paint:
alt text http://img684.imageshack.us/img684/6669/69288941.png
Text version of stack:
ui.startup.LoginScreen at localhost:51050
-> Deamon Thread [AWT-Windows] (Running)
-> Thread [AWT-Shutdown] (Running)
-> Thread [AWT-EventQueue-0] (Running)
-> Thread [DestroyJavaVM] (Running)
The answer was instead of making the call
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
from the EDT, make it execute on a new (non EDT) thread so that later when invokeAndWait is called it functions as correctly as the thread running that command is not the EDT. The amended code is as follows:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
}
});
t.start();
invokeAndWait() is meant to be called from the non-GUI thread. It sends a Runnable object to the GUI thread where it will be executed.
There's no point in sending a Runnable object from the GUI-thread to itself. It has the same effect as calling run() on the Runnable object directly.
You can check before if your current calling thread is already the event dispatcher:
private void syncExec(final Runnable r) {
try {
if (EventQueue.isDispatchThread()) r.run();
else EventQueue.invokeAndWait(r);
} catch (final Exception e) {
Throws.throwRuntime(e);
}
}
Note that SwingUtilities.invokeAndWait(Runnable) simply delegates to the EventQueue.
Based on the comments, it appears you are not repainting the frame once the actions are completed. If you do not, then the screen will only be updated at what seems to be random times (when another window moves in front, perhaps).
Inside gui.update, I suggest you make the last line:
myFrame.repaint();
(more or less, depending on your circumstances).
Edit: As it turns out, the actual problem is this loop:
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
Since there is only one application thread (which happens to be the EDT), the result of hasPerformedAction() can never change (assuming it's a simple getter). There is no other thread to change the value. Since this infinite loop is on the EDT, the GUI can never be repainted; hence it locks up.
When using XChart java library you can show your chart on button click with this code:
JButton btn = new JButton("View chart");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new SwingWrapper(yourChart).displayChart();
}
});
t.start();
}
});
try to execute your code from this
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
}
});