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();
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 trying to stop the for loop and wait until the method has finished and continue once it has called onFinish. I was suggested to use either CyclicBarrier or syncronized wait/notify, but neither of them work.
When I run the method without the "stoppers", it always reaches to the onFinish, calling all 3 System.out.prints, but when I add either CyclicBarrier or syncronized it just does not start ticking. Meaning it only prints the first line countDownTimer first call and then stops and does nothing.
Just to make it shorter I have added both stoppers here to show how I did either of them, but I did use them seperately.
What can I do to make it "tick" ?
cyclicBarrier = new CyclicBarrier(2);
object = new Object();
for (int i = 0; i < sentenceList.size() - 1; i++) {
String currentLyricLine = sentenceList.get(i).content;
long diff = sentenceList.get(i+1).fromTime - sentenceList.get(i).fromTime;
int interval = (int) (diff / sentenceList.get(i).wordCount);
if(isFirstLine) {
startLyricCountDownTimer(diff, interval, currentLyricLine, coloredLyricsTextViewFirstLine);
isFirstLine = false;
} else {
startLyricCountDownTimer(diff, interval, currentLyricLine, coloredLyricsTextViewSecondLine);
isFirstLine = true;
}
//First tried with this
synchronized (object) {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Then tried with this
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
private void startLyricCountDownTimer(final long millisInFuture, final int countDownInterval, String lyrics, final ColoredLyricsTextView coloredLyricsText){
System.out.println("countDownTimer first call" );
coloredLyricsText.setText(lyrics);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
new CountDownTimer(millisInFuture,10) {
#Override
public void onTick(long millisUntilFinished) {
System.out.println("countDownTimer second call + " + millisUntilFinished);
//Do some stuff (irrelevant since it never gets here)
}
#Override
public void onFinish() {
System.out.println("countDownTimer last call" );
//First tried with this
synchronized (object) {
object.notify();
}
//Then tried with this
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}.start();
}
});
}
If i understand correctly then it was also mentioned that I run my loop on UI thread which is why everything stops. And well I do not wish to stop the UI thread, just to wait for one countDownTimer to finish, then start a new loop.
I need to synchronize some threads at a certain checkpoint, and only after all threads have reached this point, they should continue. Is there any easy construct?
for (int v = 0; v < 10; v++) {
new Thread(new Runnable() {
#Override
public void run() {
try {
doFirst();
//checkpoint
doSecond();
} catch (Throwable e) {
e.printStackTrace();
}
}
}).start();
}
import java.util.concurrent.CountDownLatch;
private CountDownLatch countDownLatch = new CountDownLatch(10)
...
public void run() {
doFirst();
countDownLatch.countDown();
countDownLatch.await();
doSecond();
}
---- OR (1 less line of code) ----
import java.util.concurrent.CyclicBarrier;
private CyclicBarrier cyclicBarrier= new CyclicBarrier(10)
...
public void run() {
doFirst();
cyclicBarrier.await();
doSecond();
}
If you know the exact number of your threads you can use CountDownLatch from java.util.concurrent.
// First initialize latch with your number of threads
CountDownLatch latch = new CountDownLatch(N);
// Then give this instance of latch to each of your threads
// and finally at your checkpoint do
latch.countDown();
latch.await();
That's all.
You can do this using a lock object:
Integer threadCount = 10;
for (int i = 0; i < threadCount; i++)
{
new Thread(() ->
{
try
{
doFirst();
synchronized (threadCount)
{
threadCount--;
while (threadCount > 0)
threadCount.wait();
threadCount.notifyAll();
}
doSecond();
}
catch (Exception e) { e.printStackTrace(); }
}).start();
}
// all threads are started, to wait until they've finished, call threadCount.wait();
One way to do it is to synchronize your threads over a common monitor:
Object monitor = new Object();
int jobCount = 0;
public void f1(){
for (int v = 0; v < 10; v++) {
new Thread(new Runnable() {
#Override
public void run() {
try {
doFirst();
check();
doSecond();
} catch (Throwable e) {
e.printStackTrace();
}
}
}).start();
}
}
public void sleep(){}
public void check(){
synchronized(monitor){
jobCount++;
if(jobCount==10){
monitor.notifyAll();
return;
}
}
monitor.wait();
}
Things to consider:
When you call monitor.wait(), the thread where that invocation was made will go to sleep, synchronized over monitor
notifyAll() will awaken all threads that are sleeping and synch. over its recipient.
When one thread enters a synchronized block, it will take a lock over monitor. notifyAll() can only be invoked if a lock exists on its recipient
I'm trying to use threads to show a progress bar on the CLI in java while doing a long operation (generating md5sums for a batch of large files).
I've written a bit of code, and it works, but I'd like to know if I'm using threads correctly as I'm pretty new to this.
I have two class files, ProgressThreadTest.java and CountToABillion.java
CountToABillion.java:
public class CountToABillion implements Runnable {
double count = 0;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
echoCount();
}
}
}
ProgressThreadTest.java:
public class ProgressThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread doCount=new Thread(new CountToABillion());
doCount.start();
}
}
It works as expected and counts upwards on the command line.
Anyone have any comments on whether or not this is a good way to do threads?
Also, because I am updating the progress in the counting loop, it will update every 10ms. How would I change the code to only output the count once every second?
Using javax.swing.Timer is probably the easier solution:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class CountToABillion implements Runnable {
double count = 0;
Timer progressTimer;
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
progressTimer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
echoCount();
}
});
progressTimer.setRepeats(true);
progressTimer.start();
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
progressTimer.stop();
}
}
Using java.util.concurrent.ScheduledThreadPoolExecutor is the better and more scalable solution:
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CountToABillion implements Runnable {
double count = 0;
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
public void echoCount() {
System.out.println(count);
}
#Override
public void run() {
Runnable task = new Runnable() {
public void run() {
echoCount();
}
};
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
}
exec.shutdownNow();
}
}
Option 1:
int sleep = 10; //ms
int echo = 1000; //ms
for (double x=0;x<1000000000;x++) {
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((x*sleep % echo) == 0) {
echoCount();
}
}
Option 2:
Create a new Class to manage your counter, it should be able to add, reset and so on. You will have to make sure it's thread safe (writing new values in case you want to update from various threads).
Make one thread that increases the counter in given intervals
Make another thread that polls the current count in other given intervals and print.
long last=0;
#Override
public void run() {
for (double x=0;x<1000000000;x++) {
try {
doWork();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count = x;
if((System.currentTimeMillis()-last)>=1000) //post every second
{
last=System.currentTimeMillis();
echoCount();
}
}
}
This will print the count once every second assuming "work" does not take more than a second.
#Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count = i;
if(i % 100 == 0) {
echoCount();
}
}
}
By using i % 100 == 0 you're checking if i is divisible by 100 without rest value. If that's the case, it means that you have ran 100 times 10ms which is 1000ms which is 1s. So you will output your echoCountt() every second.
This is an okay way to use threads. But your thread will keep running until it has counted to 10000000 seconds.
On a sidenote, you should use 'i' instead of 'x' in for loops. It's more widely used like this and will be easier to read for experienced java developers
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.atomic.AtomicBoolean;
public class ThreadSandbox {
//static volatile boolean runLoopX = true;
static AtomicBoolean runLoopX = new AtomicBoolean();
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable(){
#Override
public void run()
{
try {
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
String userInputStr = "";
do {
System.out.println("Enter text for thread 1:");
userInputStr = userInput.readLine().trim();
System.out.println("User Input for thread 1: " + userInputStr);
} while (userInputStr.equals("e") == false && runLoopX.get()== false);
} catch (Exception e) {System.err.println(e.toString());}
runLoopX.set(true);
}
});
final Thread thread2 = new Thread(new Runnable(){
#Override
public void run()
{
try {
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
String userInputStr = "";
do {
System.out.println("Enter text for thread 2:");
userInputStr = userInput.readLine().trim();
System.out.println("User Input for thread 2: " + userInputStr);
} while (userInputStr.equals("e") == false && runLoopX.get()== false);
} catch (Exception e) {System.err.println(e.toString());}
runLoopX.set(true);
}
});
Thread thread3 = new Thread(new Runnable(){
#Override
public void run()
{
do {
if (runLoopX.get() == true) {
thread1.interrupt();
thread2.interrupt();
}
} while (runLoopX.get() == false);
}
});
thread1.start();
thread2.start();
thread3.start();
try {
thread1.join();
thread2.join();
thread3.join();
} catch (Exception e) {System.err.println(e.toString());}
}
}
Issue:
If I enter "e" for thread1 input then thread1 terminates but thread2 is still running and If I enter "e" for thread2 input then thread2 terminates but thread1 is still running.
How do I terminate both threads when "e" is entered in either threads?
you should synchronize your threads for the inputs.
but a synchronized String and made all of your threads check this string before trying to read anything
so if this string has the value "e" then the thread will terminate it self. if not just read the input but the value in the string and continue.
make sure about this String be synchronized and I would like to make it volatile
to more specific this is a bad example of threads ! if one thread will lock the application until the user enters some data. the other thread should wait in the wait queue for more performance.
in this case all of your threads will be kept in the ready queue and this will consume the CPU utilization.
to solve this problem try to use Lock and Conditions.
this is a fast pesedo-code to solve the problem on sockets :
public class ThreadSandbox {
public static syncrnized boolean continueWork = true;
public static void main(String[] args) {
final Thread thread1 = new Thread(new Runnable(){
#Override
public void run()
{ while(continueWork){
try {
socket.setSoTimeout(5 *1000);
//READ str FROM SOCKET
if(str.equals("e")) {
continueWork =false;
}
} catch (TimeoutException e) {
System.err.println(e.toString());
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
});
final Thread thread2 = new Thread(new Runnable(){
#Override
public void run()
{ while(continueWork){
try {
socket.setSoTimeout(5 *1000);
//READ str FROM SOCKET
if(str.equals("e")) {
continueWork =false;
}
} catch (TimeoutException e) {
System.err.println(e.toString());
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
});
thread1.start();
thread2.start();
}
}