Thread runOnUiThread pausing/resume after notify() not continue - java

Iam making app for listening .mp3 words in greek language and displaying them after 2000ms but when i pause thread and then notify() back thread never runs again... TextView is changing every 2000ms but when i pause it and notify() run() block is not executing anything anymore and app crashes.. What iam doing wrong ?
class MyinnerThread implements Runnable {
String name;
Thread tr;
boolean suspendFlag;
int i = 0;
MyinnerThread(String threadname) {
name = threadname;
tr = new Thread(this, name);
suspendFlag = false;
tr.start();
}
public void run() {
try {
while(!suspendFlag){
runOnUiThread(new Runnable() {
#Override
public void run() {
if(i == 0){tv1.setText("trhead1");}
if(i == 1){tv2.setText("trhead2");}
if(i == 2){tv3.setText("trhead3");}
if(i == 3){tv4.setText("trhead4");}
if(i == 4){tv5.setText("trhead5");}
if(i == 5){tv6.setText("trhead6");}
if(i == 6){tv7.setText("trhead7");}
if(i == 7){tv8.setText("trhead8");}
synchronized(signal) {
while(suspendFlag) {
try {
signal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread.sleep(2000);
i++;
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
}
void mysuspend() {
suspendFlag = true;
}
void myresume() {
synchronized(signal) {
suspendFlag = false;
signal.notify();
}
}
}
EDIT: Final code here and working !
run() {
try {
while(true){
synchronized(signal) {
while(suspendFlag) {
try {
signal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
//....
}
}
});
Thread.sleep(2000);
i++;
}
}
}
}

signal.wait() is called from within the UI thread (I assume, runOnUIThread will execute the given Runnable on the UI thread). This will block/freeze the UI. Take it out of the run() method and put into the threads 'main loop'.
Rethink the main loop while (!suspendFlag)! This will abort the entire task instead of just suspending it.
Finally, make suspendFlag volatile to avoid visibility issues.

Related

Thread imageView update speeds up

I have a thread that is used to spin an imageview as other things happen in the background. It works great for spinning, but I've noticed as I turn it on and off (based on the spinningMain variable) the button starts to spin faster and faster and faster.
I'm unsure what the cause of this is as the thread is told to sleep every 100ms.
If it helps I also have another thread (runnable thread) which runs the main code in between, which I was wondering whether it was disrupting the thread?
The imageView update thread is:
final Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(100);
runOnUiThread(new Runnable() {
#Override
public void run() {
if (spinningMain == true) {
// update TextView here!
if (spinningAngleMain >= 360) {
spinningAngleMain = 0;
} else {
spinningAngleMain += 5;
}
imageButton.setRotation(spinningAngleMain);
}
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
And the Second thread is pretty much made as follows
new Thread(new Runnable() {
#Override
public void run() {
if (searchStateButton == true) {
//do all my stuff
}
My boolean variables are set to volatile if that helps as well.

I need to stop thread when progress bar reaches 0 in android

I need stop thread and handler when my progress bar reaches 0 from 100 when thread runs the progress bar reaches but the progressStatus value going in negative please help me to stop thread after progress bar reaches 0
new Thread(runn =new Runnable() {
public void run() {
while (progressStatus <= 100) {
progressStatus += doWork();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
handler.post(runn1=new Runnable() {
public void run() {
bar.setProgress(progressStatus);
i=-1;
if(bar.getProgress()==0)
{
handler.removeCallbacks(runn);
handler.removeCallbacks(runn1);
System.out.println("Reached");
congrats.setVisibility(View.VISIBLE);
restart.setVisibility(View.VISIBLE);
rightbutton.setVisibility(View.GONE);
wrongbutton.setVisibility(View.GONE);
}
}
});
}
}
private int doWork() {
return i;
}
}).start();
your program is not thread safe, you actually reading and writing a variable (progressStatus) from two different threads, you must avoid doing that or if you want to do that you must use synchronized block. In order to solve your problem you can do this way:
Thread t;
progressStatus = 100;
t = new Thread(runn =new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
// Update the progress bar
handler.post(runn1=new Runnable() {
public void run() {
bar.setProgress(progressStatus);
progressStatus=progressStatus-1;
if(bar.getProgress()==0)
{
handler.removeCallbacks(runn);
handler.removeCallbacks(runn1);
System.out.println("Reached");
congrats.setVisibility(View.VISIBLE);
restart.setVisibility(View.VISIBLE);
rightbutton.setVisibility(View.GONE);
wrongbutton.setVisibility(View.GONE);
t.interrupt();
}
}
});
another way that i recommend you is using ScheduledThreadPoolExecutor with the function scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit). something like:
final ScheduledThreadPoolExecutor myTimer = new ScheduledThreadPoolExecutor(1);
myTimer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
getActivity().runOnUiThread(new Runnable(){
#Override
public void run(){
}
});
}
}
}, 0,10, TimeUnit.MILLISECONDS);
and in order to close it use myTimer.shutdownNow();

How to correctly block Eclipse job

I am using org.eclipse.core.runtime.jobs.JOB to execute backgrounds task that also gathers data from UI controls.
I want to "block" until job is finished (the trigger for the JOB is some ui button event)
Job job = new Job("Job") {
protected IStatus run(IProgressMonitor arg0) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
System.out.println(i);
}
}
});
return Status.OK_STATUS;
}
};
job.schedule();
job.join(); //<-- Doesn't block!!!
if (job.getResult().isOK())
System.out.println("success"); //<-- Result is ok!!
else
System.out.println("failed");

Black view when starting new thread

In my android application I want an automatically refresh every 60 seconds. So I tried it like this:
public void refresh_check() {
Thread myThread = new Thread()
{
int counter = 0;
#Override
public void run() {
MyActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
while (counter < 60) {
try {
Thread.sleep(1000);
counter += 1;
System.out.println("Counter: " + counter);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
refresh();
}});
super.run();
}
};
myThread.start();
}
This works in the way that it prints the counter into logcat but in my Application I get a black view. refresh() is just a function with a http request, and this works alone, so the mistake has to be in the thread at any place :/ Can someone help?
You are not utilizing the Thread correctly. Running long tasks on the UI thread is just like not using a Thread at all. To accomplish what you need you should do it like this:
public void refresh_check() {
Thread myThread = new Thread()
{
int counter = 0;
#Override
public void run() {
while (counter < 60) {
try {
Thread.sleep(1000);
counter += 1;
System.out.println("Counter: " + counter); //I think this may cause exception, if it does try removing it
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
refresh(); // In refresh(), use TextView.post(runnable) to post update the TextView from outside the UI thread or use handlers
}});
super.run();
};
myThread.start();
}
Also, take a look at AsyncTask class, it enables you to run long tasks outside UI thread (doInBackground()) as well as update UI with the result from (onPostExecute())

java: Printing odd even numbers using 2 threads

I am trying to print odd and even numbers using 2 different threads alternately. I was able to achieve it using wait, notify and synchronize block but now i want to evaluate if we can achieve it without using wait, notify and synchronize.
Following is the code i have but its not working:
public class OddEvenUsingAtomic {
AtomicInteger nm = new AtomicInteger(0);
AtomicBoolean chk = new AtomicBoolean(true);
public static void main(String args[]) {
final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (pc.chk.compareAndSet(true, false)) {
System.out.println("Odd: " + pc.nm.incrementAndGet());
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
if (pc.chk.compareAndSet(false, true)) {
System.out.println("Even: " + pc.nm.incrementAndGet());
}
}
}
}).start();
}
}
Any ideas?
I created another version after suggestions from Bruno which seems to be working better:
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class OddEvenUsingAtomic {
AtomicInteger nm = new AtomicInteger(0);
AtomicBoolean chk = new AtomicBoolean(true);
public static void main(String args[]) {
final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (pc.chk.get() == Boolean.TRUE) {
System.out.println("Odd: " + pc.nm.incrementAndGet());
pc.chk.compareAndSet(true, false);
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
if (pc.chk.get() == Boolean.FALSE) {
System.out.println("Even: " + pc.nm.incrementAndGet());
pc.chk.compareAndSet(false, true);
}
}
}
}).start();
}
}
The code is not correctly synchronized, that's the problem.
The following execution order is allowed in your code:
First thread sees chk == true, sets it to false and enters the if block.
Second thread sees chk == false, sets it to true and enters the if block.
Now, you have 2 threads both inside their if blocks, getting ready to:
incrementAndGet() the number
Print it.
Therefore, you have absolutely no control on what is going to happen.
You can have any of the threads call incrementAndGet(), therefore you can have thread "Odd" printing, first, an odd number, and later, an even number.
You can have the first thread print the number, loop, see that the condition is satisfied again (since the second thread has set chk to true again, print, all of this before the second thread had the chance to print).
As you can see, to achieve the result you want, you must have the following operations done atomically:
compareAndSet() the boolean
incrementAndGet() the number
print it
If the 3 operations are not atomic, then you can have the threads being scheduled to run the operations in any possible order, you have no control on the output. The easiest way to achieve this is to use a synchronized block:
public static void main(final String... args) {
final Object o = new Object();
// ... thread 1 ...
synchronized(o) {
if (boolean is in the expected state) { change boolean, get number, increment, print }
}
// ... thread 2 ...
synchronized(o) {
if (boolean is in the expected state) { change boolean, get number, increment, print }
}
}
Here are two threads printing odds and evens with no wait, notify, or synchronized (at least not in the code you can see):
import java.util.concurrent.*;
public class ThreadSignaling {
public static void main(String[] args) {
BlockingQueue<Integer> evens = new LinkedBlockingQueue<>();
BlockingQueue<Integer> odds = new LinkedBlockingQueue<>();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(() -> takeAndOfferNext(evens, odds));
executorService.submit(() -> takeAndOfferNext(odds, evens));
evens.offer(0);
}
private static void takeAndOfferNext(BlockingQueue<Integer> takeFrom,
BlockingQueue<Integer> offerTo) {
while (true) {
try {
int i = takeFrom.take();
System.out.println(i);
offerTo.offer(i + 1);
} catch (InterruptedException e) {
throw new IllegalStateException("Unexpected interrupt", e);
}
}
}
}
class MultiThreading {
Integer counter = 0;
Thread even;
Thread odd;
boolean flagEven = true;
boolean flagOdd;
class ThreadEven implements Runnable {
#Override
public void run() {
try {
while (counter < 100) {
if (flagEven) {
System.out.println(counter);
counter++;
flagEven = false;
flagOdd = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ThreadOdd implements Runnable {
#Override
public void run() {
try {
synchronized (even) {
while (counter < 100) {
if (flagOdd) {
System.out.println(counter);
counter++;
flagOdd = false;
flagEven = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void start() {
even = new Thread(new ThreadEven());
odd = new Thread(new ThreadOdd());
even.start();
odd.start();
}
}
}
call in the main method
new MultiThreading().start();

Categories