in my app I have a timer and stop/start buttons. Timer works with thread
when I click the button my timer starts working. when I click stop and start it seems like my thread works as 2 parallel threads.
How to stop the first thread and create the second ?
Here is the code
timer = new Thread(new Runnable() {
#Override
public void run() {
final boolean cont = mSharedPreferences.getBoolean("continuesMode", false);
final boolean statemant = !stopedAlgo && !mUserStop;
if(!statemant){
timerMinutes = 0;
timerHours = 0;
}
while(statemant){
time="";
if(timerMinutes>=60){
timerMinutes = 0;
timerHours++;
}
if(timerHours<10)
time = "0" + String.valueOf(timerHours)+":";
else
time = String.valueOf(timerHours)+":";
if(timerMinutes<10)
time += "0" + String.valueOf(timerMinutes);
else
time += String.valueOf(timerMinutes);
HeadSense.this.runOnUiThread(new Runnable(){
public void run(){
boolean state = mContinuousMode && !stopedAlgo && !mUserStop ;
if(!stopedAlgo && cont){
mTfsValue.setText(time);
timerMinutes++;
}
else{
timerMinutes = 0;
timerHours = 0;
}
}
});
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
timer.start();
Of my understanding your first Thread (or second) will never stop because of the following line:
final boolean statemant = !stopedAlgo && !mUserStop;
This is final, and will only be evaluated once and never change. If it evalutes to true when you create the Thread it will stay true and keep running.
You need to declare your boolean statemant as volatile here. What this does is give a hint to the compiler that certain optimizations cannot be taken because this variable is modified by external threads.
Also, you would be interested in this - How to stop a java thread gracefully?
Related
I am trying to print even odd numbers using two threads with interrupt method.
I refereed code from internet and wrote a code showing below.It prints properly but after prints 20,program is continuing it's execution.
What change do i have to make in the code to stop the execution of the program?
Without oldNum check code is working fine. Is there any logic to provide oldNum check ?
If I remove Thread.sleep(1000L) from Line-a then it only prints "Even Thread prints 20" and continue execution.What is happening here?
Provided break points inside run() method and inside for loop of main method ,run() methods break points are not hitting.Why this is happening?
In short I want to know what is the code flow here.
Thanks
Vikash
public class PrintOddEvenUsingInterrupt {
public static volatile int count;
public static void main(String[] args) throws InterruptedException {
Thread oddThread = new Thread(new OddInterruptThread(), "Odd Thread ");
Thread evenThread = new Thread(new EvenInterruptThread(),"Even Thread ");
oddThread.start();
evenThread.start();
for (int i = 0; i < 20; i++) {
count++;
oddThread.interrupt();//Break points works here
evenThread.interrupt();
Thread.sleep(1000L);// Line-a
}
}
static class OddInterruptThread implements Runnable {
public void run() {
int oldNum = 0;//Break points doesn't works here
while (true) {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
}
if (oldNum != count && count % 2 == 1) {
System.out.println(Thread.currentThread().getName()
+ " prints " + count);
oldNum = count;
}
}
}
}
static class EvenInterruptThread implements Runnable {
public void run() {
int oldNum = 0;//Break points doesn't works here
while (true) {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
}
if (oldNum != count && count % 2 == 0) {
System.out.println(Thread.currentThread().getName()
+ " prints " + count);
oldNum = count;
}
}
}
}
}
The reason your program is not stopping is: while your main thread exits, your odd and even threads sleeps in infinite loop.
You will need to define a stopping condition for your threads to come out.
One way to achieve this is via using conditions.
Eg:
public volatile static boolean oddFinished = false;
public volatile static boolean evenFinished = false;
Then in your threads, instead of looping infinitely, loop against condition
while (! oddFinished){
// also change your thread sleep to sleep for fewer time interval (say 1000L or whatever your program wants to wait for)
}
Do the same for even thread...
while (! evenFinished){
// also change your thread sleep to sleep for fewer time interval (say 1000L or whatever your program wants to wait for)
}
And in the main thread, you can add the following code after your for loop ends...
oddFinished = true;
evenFinished = true;
oddThread.join();
evenThread.join();
This will allow your code to stop gracefully.
I think the simplest solution will be to make your threads demons.
Just add the following lines before starting your thteads.
oddThread.setDaemon(true);
evenThread.setDaemon(true);
And your program will exit immediately after exiting from main.
I am doing a sample program with wait() and notify(), but when notify() is called, more than one thread is wakes up instead of one.
The code is:
public class MyQueue<T> {
Object[] entryArr;
private volatile int addIndex;
private volatile int pending = -1;
private final Object lock = new Object();
private volatile long notifiedThreadId;
private int capacity;
public MyQueue(int capacity) {
entryArr = new Object[capacity];
this.capacity = capacity;
}
public void add(T t) {
synchronized (lock) {
if (pending >= 0) {
try {
pending++;
lock.wait();
System.out.println(notifiedThreadId + ":" + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (pending == -1) {
pending++;
}
}
if (addIndex == capacity) { // its ok to replace existing value
addIndex = 0;
}
try {
entryArr[addIndex] = t;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("ARRAYException:" + Thread.currentThread().getId() + ":" + pending + ":" + addIndex);
e.printStackTrace();
}
addIndex++;
synchronized (lock) {
if (pending > 0) {
pending--;
notifiedThreadId = Thread.currentThread().getId();
lock.notify();
} else if (pending == 0) {
pending--;
}
}
}
}
public class TestMyQueue {
public static void main(String args[]) {
final MyQueue<String> queue = new MyQueue<>(2);
for (int i = 0; i < 200; i++) {
Runnable r = new Runnable() {
#Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
queue.add(Thread.currentThread().getName() + ":" + i);
}
}
};
Thread t = new Thread(r);
t.start();
}
}
}
After some time, I see two threads being wake up by single thread. The output looks like:
91:114
114:124
124:198
198:106
106:202
202:121
121:40
40:42
42:83
83:81
81:17
17:189
189:73
73:66
66:95
95:199
199:68
68:201
201:70
70:110
110:204
204:171
171:87
87:64
64:205
205:115
Here I see 115 thread notified two threads, and 84 thread notified two threads; because of this we are seeing the ArrayIndexOutOfBoundsException.
115:84
115:111
84:203
84:200
ARRAYException:200:199:3
ARRAYException:203:199:3
What is the issue in the program?
What is the issue in the program?
You have a couple of problems with your code that may be causing this behavior. First, as #Holder commented on, there are a lot of code segments that can be run by multiple threads simultaneously that should be protected using synchronized blocks.
For example:
if (addIndex == capacity) {
addIndex = 0;
}
If multiple threads run this then multiple threads might see addIndex == capacity and multiple would be overwriting the 0th index. Another example is:
addIndex++;
This is a classic race condition if 2 threads try to execute this statement at the same time. If addIndex was 0 beforehand, after the 2 threads execute this statement, the value of addIndex might be 1 or 2 depending on the race conditions.
Any statements that could be executed at the same time by multiple threads have to be properly locked within a synchronized block or otherwise protected. Even though you have volatile fields, there can still be race conditions because there are multiple operations being executed.
Also, a classic mistake is to use if statements when checking for over or under flows on your array. They should be while statements to make sure you don't have the class consumer producer race conditions. See my docs here or take a look at the associated SO question: Why does java.util.concurrent.ArrayBlockingQueue use 'while' loops instead of 'if' around calls to await()?
I have applied two process critical section solution to two threads instead of processes. My code is:
class Main
{
static boolean flag[];
static int turn;
static int count;
synchronized static void print(char ch,int n)
{
int i;
System.out.println(ch);
for(i=0;i<n;i++){
System.out.println(i);
}
}
public static void main(String[] args) throws IOException
{
flag = new boolean[2];
flag[0] = flag[1] = false;
turn = 0;
count = 0;
ThreadLevelOne t1 = new ThreadLevelOne('a');
ThreadLevelTwo t2 = new ThreadLevelTwo('b');
t1.start();
t2.start();
}
static class ThreadLevelOne extends Thread{
private char ch;
public ThreadLevelOne(char ch){
this.ch = ch;
}
public void run(){
while(true)
{
flag[0] = true;
turn = 1;
while(flag[1] && turn == 1);
print(ch,3);
count++;
System.out.println("Counter is : " + count);
flag[0] = false;
}
}
}
static class ThreadLevelTwo extends Thread{
private char ch;
public ThreadLevelTwo(char ch){
this.ch = ch;
}
public void run()
{
while(true)
{
flag[1] = true;
turn = 0;
while(flag[0] && turn == 0);
print( ch, 4);
count++;
System.out.println("Counter is : " + count);
flag[1] = false;
}
}
}
}
On executing the above code, it does not run infinitely but halts at arbitrary counter value on each execution. Is this a valid application of the two process solution to threads? If yes, then why is program halting at arbitrary counter value? If no, then how can this be achieved in threads?
Edit after the answer of codeBlind:
output: Program execution halts at this stage
Even if i dont increment the counter value, then also the program halts after a certain time
You're a victim of concurrently executing non-atomic operations, specifically count++, as well as the way you are using flags in each thread. But for simplicity's sake, let's talk about count++. The ++ operator actually executes three commands, each in their own clock-cycle:
read value of count
add 1 to value retrieved from count
store new value into count
The problem you're seeing is a result of these commands being interleaved across two threads. Thread A may not have stored the new count value by the time that Thread B attempts to read it.
A quick fix would be to use AtomicInteger for count instead of primitive int - AtomicInteger guarantees thread safety for integer operations.
EDIT
There are other race conditions in this code as well. Each thread's while loop argument (e.g. flag[0] && turn == 0) is non-atomic, but both threads are capable of modifying turn. You've left open the possibility that one thread could set turn before the other thread's while argument is fully evaluated, causing your threads to deadlock down the road.
If you only wish to guarantee that each thread must not be inside the while loop while the other thread is, then you should instead write each of your while loops to look something like this:
while(true){
synchronized(Main.class){
print( ch, 4);
count++;
System.out.println("Counter is : " + count);
}
}
If you want to guarantee that each thread must "take turns", you should look into using wait() and notify().
Ok so I figured it out, the issue is that each thread needs to pause in order for the other thread to run.
Instead of just spinning the cpu using:
while(flag[0] && turn == 0);
You need to pause the thread by calling the sleep method.
while(flag[0] && turn == 0){
try {
this.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
So, I ran a test and the results make no sense to me. Lets consider the following code:
ThreadStuffCounter counter_1 = new ThreadStuffCounter(1);
while(counter_1.doProceed) {
Thread.sleep(500);
Thread thread = new Thread(counter_1);
thread.start();
}
With the Runnable as follows:
package test;
public class ThreadStuffCounter implements Runnable {
public volatile boolean doProceed = true;
private int id = -1;
public volatile int i = -1;
public ThreadStuffCounter(int id) {
this.id = id;
}
#Override
public void run() {
for (i = 0; i < 10; i++) {
System.out.println("i = " + i + " in runnable id = " + id);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
doProceed = false;
}
}
Only one instance of counter is shared between threads. It takes less time for another thread to start then even one increment to be made on the counter.doProceed should, as I understand never be set to false and the loop should continue indefinitely until I get an out of memory exception and cannot start any more threads.
How is it possible for the loop to exit?
EDIT: Modified code to make sure the answer below is correct.
package test;
public class ThreadStuffCounter implements Runnable{
public volatile boolean doProceed = true;
private int id = -1;
volatile int i = -1;
public ThreadStuffCounter(int id){
this.id = id;
}
#Override
public void run() {
i = 0;
while (i < 10){
System.out.println("i = " + i + " in runnable id = " + id +
"; from thead id = " + Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
ThreadStuff.doProceed = false;
}
}
And
package test;
public class ThreadStuff {
public static volatile boolean doProceed = true;
public static void main (String[] args) throws InterruptedException{
ThreadStuffCounter counter_1 = new ThreadStuffCounter(1);
while(doProceed){
Thread.sleep(500);
Thread thread = new Thread(counter_1);
thread.start();
}
}
}
Also, it appears more then n threads are needed if you are running for i < n. You need however many, so that n threads increment at the same time.
When at least one of the threads executes the for loop and i value is greater or equal than 10, then doProceed variable will be false (yes, this may happen), and since it's volatile this will stop the execution of the while loop that creates and starts new threads. Then, is up to all the threads to just finish executing the code of the for loop and then finishing their execution. This seems to happen because the time to start a new thread in your environment is slower than the time for a current thread to finish its execution. Also, note that several threads may increase i value, which will accelerate the for loop execution.
Probably if you loop to a higher value (not tested) then this could generate an infinite loop and the application will break when there aren't enough resources to create and start new threads.
After some tests using the limit as 10, 50 and 1000. I noticed that when you have a bigger value, since lots of threads are created, all of them increase the value of i at the same time and i slowly starts to get closer to the limit value set in the for loop. Description of my current environment:
OS: Windows 7 Professional 64 bits
Processor: Intel(R) Core(TM) i5-2520M CPU # 2.50GHz (4 CPUs), ~2.5GHz
Ram: 8192MB
I am working on an app that counts the number of questions marks in a few paragraphs of text.
After the scanning is done (which takes no time at all) I would love to have the total presented after the number goes from 0 to TOTAL. So, for 10: 0,1,2,3,4,5,6,7,8,9 10 and then STOP.
I have tried a couple of different techniques:
TextView sentScore = (TextView) findViewById(R.id.sentScore);
long freezeTime = SystemClock.uptimeMillis();
for (int i = 0; i < sent; i++) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
sentScore.setText(sent.toString());
}
}
Also I tried this:
for (int i = 0; i < sent; i++) {
// try {
Thread.sleep(500);
} catch (InterruptedException ie) {
sentScore.setText(i.toString());
}
}
I am sure these are both completely amateur attempts. Any help would be much-appreciated.
Thanks,
Richard
I've used a more conventional Android-style animation for this:
ValueAnimator animator = new ValueAnimator();
animator.setObjectValues(0, count);
animator.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
view.setText(String.valueOf(animation.getAnimatedValue()));
}
});
animator.setEvaluator(new TypeEvaluator<Integer>() {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return Math.round(startValue + (endValue - startValue) * fraction);
}
});
animator.setDuration(1000);
animator.start();
You can play with the 0 and count values to make the counter go from any number to any number, and play with the 1000 to set the duration of the entire animation.
Note that this supports Android API level 11 and above, but you can use the awesome nineoldandroids project to make it backward compatible easily.
Try this:
private int counter = 0;
private int total = 30; // the total number
//...
//when you want to start the counting start the thread bellow.
new Thread(new Runnable() {
public void run() {
while (counter < total) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.post(new Runnable() {
public void run() {
t.setText("" + counter);
}
});
counter++;
}
}
}).start();
The question is very old, but I am posting this so that it would help someone else.
I have used these 2 amazing libraries.
Try them
https://github.com/MasayukiSuda/CountAnimationTextView
Or
2. https://github.com/robinhood/ticker
Hope this helps :) Happy Coding!!!
Use TextSitcher
for the best effects. It will transform the text softly.
When coming to the change of the text use the below Code.
> int number = 0;
> Timer obj = new Timer();
> TimerTask tt = new TimerTask() {
> #Override public void run() {
> // TODO Auto-generated method stub
> textView.setText(number++);
> if(number < score)
> obj.schedule(tt, 200); } };
> obj.schedule(tt, 200);
Use a worker thread to do the waiting and update your UI thread.
You could use an AsyncTask, though it might be an overkill for this job. If you use this, In the doInBackground() loop over the number of sleep periods and after every sleep period, update the count in the UIthread.
There you go! Slukain just gave you the working code :P
Maybe try changing the for loop to something like:
int count = 0;
while (count != sent) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
count++;
sentScore.setText("" + count);
freezeTime = SystemClock.uptimeMillis();
}
}