I made this sample to test wait/notify functionalities:
public class WaitingTest implements Runnable {
Thread b = new Thread(this,"query");
int total=0;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
for(int i=0; i<1000000000 ; i++){
total += i;
}
}
}
}
The problem is, my output should be zero since Im notifying the wait after 10ms and my thread takes longer than this to execute its work. So, my output should be zero, instead its coming another value. What am I missing?
EDIT:
public class WaitingTest implements Runnable {
Thread b = new Thread(this,"query");
int total=0;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
b.notify();
for(long i=0; i<100000 ; i++){
total += i;
}
}
}
}
The javadoc for wait() states
This method causes the current thread (call it T) to place itself in
the wait set for this object and then to relinquish any and all
synchronization claims on this object
So when you do
b.wait(10);
the current thread releases the synchronized it has on b and your other thread can therefore acquire it in the run() method coming from
b.start();
The total starts increasing. When 10ms is up, the main thread reacquires the lock on b (assuming the run() completes) and prints out the total. Note that your total will most likely overflow.
You get overflow (you cannot sum up these 1000000000 non-negative ints and store the result in an int). Define total as long. Also call b.notify() or b.notifyAll() after your loop in the run method is done.
Also, change wait(10) to just wait(), this will make the printing thread wait for
the calculating thread as much as needed (and not just for 10 milliseconds).
This is the proper way of doing this test.
Regarding the thread syncing part I suggest you read something e.g. these old articles.
http://www.javaworld.com/article/2074217/java-concurrency/java-101--understanding-java-threads--part-1--introducing-threads-and-runnables.html
http://www.javaworld.com/article/2074318/java-concurrency/java-101--understanding-java-threads--part-2--thread-synchronization.html
http://www.javaworld.com/article/2071214/java-concurrency/java-101--understanding-java-threads--part-3--thread-scheduling-and-wait-notify.html
http://www.javaworld.com/article/2074481/java-concurrency/java-101--understanding-java-threads--part-4---thread-groups--volatility--and-threa.html
Related
I am trying to print even and odd using two separate threads which communicate with each other by wait and notify.
I do know that i refers to Integer object which is in heap. hence changes made by one thread should be visible to both thread. Also I am using volatile keyword for declaration of Integet i.
I cant seem to understand how value of variable i is shown as 1 even after it has been incremented.
The output of code is
Even Thread got lock i=1
Even Thread waiting.. i=1
Odd Thread got lock i=1
Odd Thread : i=2
Odd Thread Run called NotifyAll
Odd Thread got lock i=2
Odd Thread waiting.. i=2
Even Thread woken up.. i=1
Even Thread waiting.. i=1
package programs;
public class EvenOdd {
static Object lck = new Object();
volatile static Integer i=1;
volatile static Integer N = 1000;
public static void main(String args[]){
EvenRunner e = new EvenRunner(lck, i, N);
OddRunner o = new OddRunner(lck, i, N);
Thread t1 = new Thread(e,"Even Thread ");
Thread t2 = new Thread(o,"Odd Thread ");
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch(InterruptedException ex) {
System.out.println("Interrupted : "+ex);
}
}
}
class EvenRunner implements Runnable{
Object lck;
Integer i;
Integer N;
EvenRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
#Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Even Thread got lock i="+i);
while(i%2==1){
try {
System.out.println(" Even Thread waiting.. i="+i);
lck.wait();
System.out.println(" Even Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Even Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
class OddRunner implements Runnable{
Object lck;
Integer i;
Integer N;
OddRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
#Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Odd Thread got lock i="+i);
while(i%2==0){
try {
System.out.println(" Odd Thread waiting.. i="+i);
lck.wait();
System.out.println(" Odd Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Odd Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
Expected Result: should be that other thread should also see the value of variable I as 2 after it has been incremented.
Actual result: value of variable i is read as 1 by other thread even after incrementing it.
Expected output should be that other thread should also see the value of variable I as 2 after it has been incremented.
When you construct evenRunner and oddRunner, you're copying the same Integer reference into each class as an instance field.
But Integer is immutable - when you execute ++i; that changes the field to refer to a different Integer object. It doesn't modify the content of the existing integer object... so your two threads are operating on entirely separate fields, and won't interact at all.
If you want to have a single object that both threads can modify, use AtomicInteger instead.
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.
In the problem I am trying to solve, each thread has to read the whole file, (maybe each thread will deliver its content to another task or any other purpose). After reading it, the thread should sleep a bit then try to read the file again, and only a given number(n) of threads should read the file. My attempt to solve this dealing with controling the amount of threads working is in the code below :
import java.util.*;
class Reader implements Runnable{
Thread t;
Controler c;
public Reader(Controler c){
t = new Thread(this);
this.c = c;
t.start();
}
public void run(){
Random ran = new Random();
int napTime;
while(true){
try{
w.intentarLeerArchivo(t);
//Specification says that each reader
//should wait a bit before trying to
//read the file again
napTime = ran.nextInt(1000);
t.sleep(napTime);
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
}
class Controler{
Random ran;
LinkedList <Reader> readers;
int n;
int count;
public Controler(int n){
readers = new LinkedList <Reader>();
this.n = n;
count = 0;
ran = new Random();
}
public synchronized void getPermission(){
try{
while(count >= n){
wait();
}
notify();
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
public synchronized void increaseCount(){
count++;
}
public synchronized void decreaseCount(){
count--;
System.out.println("There are " + count + " threads reading");
}
public void intentarLeerArchivo(Thread t){
int readTime = 1000;
try{
getPermission();
System.out.println("Thread " + t.getId() +" empezó a leer");
increaseCount();
t.sleep(readTime);
System.out.println("Thread " + t.getId() +" is reading");
System.out.println("Thread " + t.getId() + " finished reading");
decreaseCount();
} catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
class Initializer{
int numReaders;
int maxReaders;
public Initializer(int numReaders, int maxReaders){
this.numReaders = numReaders;
this.maxReaders = maxReaders;
}
public void init(){
Controler c = new Controler(maxReaders);
for(int i = 0; i < numReaders; i++){
new Reader(c);
}
}
}
public class FileShare{
public static void main(String [] args){
Initializer c = new Initializer(100, 50);
c.init();
}
}
There are a few lines I wrote in order to debug. They print the state of each thread and the number of threads that are reading whenever one of them ends reading. But when I run the program, it turns out that suddenly there are more Threads reading the file than the ones there were supposed to be doing so. I guess it has something to do with my synchronization manipulation. What am I doing wrong?
When a thread is in the
while(...){wait()}
section of your implementation, it wait until someone notify it to go on. Right now, when you finish waiting, you notify right away.
Think about it, if once I get in I notify someone to come, he will not wait until I'm done before coming in. You want to use notify when you leave the file.
I'm trying to get into the nitty gritty of understanding how wait and notifyAll work and have hit a roadblock.
This program downloads a long text document, starts multiple threads to count characters and then outputs the count totals.
I'm using wait and notifyAll to control the thread execution so that they are completed in alphabetical order. Here's the code. I'll follow with an explanation of the problem.
public class Test {
public static void main(String[] args) {
//code that reads in the data
LongTask a = new LongTask(buffer, 'a', "Thread_a", 0);
a.start();
LongTask b = new LongTask(buffer, 'b', "Thread_b", 1);
b.start();
//Repeat code for all other characters
a.join();
System.out.println("Alphabet count is: " + SharedResults.getResults());
LongTask class contains constructor and run()
public class LongTask extends Thread {
//Instance variables created here
//LongTask constructor
public LongTask (StringBuffer buffer, char target, String name, int turn)
{
super(name);
this.sharedData = sharedData;
inputData = buffer;
this.target = target;
this.turn = turn;
}
//Run method iterates through input data and counts matching characters,
//then calls addToResults
public synchronized void run()
{
//Thread t = Thread.currentThread();
String name = this.getName();
int runTurn = this.turn;
System.out.println(name + " running - Turn " + runTurn);
Integer count = 0;
for (int i = 0; i < inputData.length(); i++) {
if (inputData.charAt(i) == target) {
count ++;
}
}
ResultsEntry newResult = new ResultsEntry(count, target);
SharedResults.addToResults(newResult, turn);
}
}
SharedResults class adds results to Array. addToResults method performs this action and controls the synchronization.
public class SharedResults extends Thread{
//Code that creates array
//Code for SharedResults constructor
public synchronized static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread t = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
while (turn != results.size()){
try {
System.out.println("Wait printout");
t.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
t.notifyAll();
}
Here's what I'm seeing when I watch this step through in Debug.
-Input executes and all LongTask threads start
(Thread_a should be the first thread to execute addToResults)
-Some threads (not Thread_a) hit the while evaluation of addToResults and do not proceed
-Thread_a hits the while evaluation and fully executes. (Now it should be Thread_b's turn)
-Thread_e executes the "Wait printout" (just a debugging feature that tells me when a thread is waiting) and then the program hangs.
It looks to me like I haven't set up wait correctly. The program actually worked (or appeared to be) correctly until I added in the sysout. Any ideas what's going on here?
To answer my own question,
This was covered in this thread.
The problem is that notifyAll() notify all of that object's threads that are waiting. Because I was calling wait() on each thread, the notifyAll() from another thread wasn't notifying any of the other threads.
As suggested by the linked post, I created a static synchronized object and called the wait and notify methods on that object. The resulting code looked like this:
private static final Object LOCK = new Object();
public static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread thread = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
synchronized (LOCK){
while (turn != results.size()){
try {
System.out.println(thread.getName() + " is waiting");
LOCK.wait();
} catch (InterruptedException e) {}
}
System.out.println(thread.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
LOCK.notifyAll();
}
}
Thanks to all who commented!
I have a Thread Object - ThreadB which add numbers 1 - 100. I create 2 instances of it - b & c.
Start the 2 threads(different instances) and run it.
Result:
Waiting for b to complete...
Total is: 4950
Waiting for c to complete...
Why does my second instance does not complete...
Java code:
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
ThreadB c = new ThreadB();
b.start();
c.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
synchronized(c){
try{
System.out.println("Waiting for c to complete...");
c.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + c.total);
}
}
}
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
Because your second ThreadB finishes while you're in the block synchronized on the first ThreadB. You then wait on your second ThreadB, but the notify() has already happened so you'll wait there forever.
Note that this isn't guaranteed, and your program will probably work sometimes.
Put some print statements inside your ThreadB class to test this theory.
If you just wish to wait for both threads to complete you should use the Thread join method, which is specifically designed for this.
It also makes use of wait and notify (or rather notifyAll) underneath the hood.
Your code will be much cleaner too:
System.out.println("Waiting for b to complete...");
b.join();
System.out.println("b completed.");
System.out.println("Waiting for c to complete...");
c.join();
System.out.println("c completed.");
System.out.println("b's total is " + b.total");
System.out.println("c's total is " + c.total");
This is not the right way to approach the problem. You are trying to serialize two independent threads, which is pointless.
If your only purpose is to give the user some feedback, you make each thread inform the user that it terminated its job before quitting:
class ThreadB extends Thread{
String name;
int total;
public ThreadB(String name){
this.name = name;
}
#Override
public void run(){
System.out.println("Waiting for "+name+" to complete...");
for(int i=0; i<100 ; i++){
total += i;
}
System.out.println(name+" completed. Total is "+total);
}
}
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB("b");
ThreadB c = new ThreadB("c");
b.start();
c.start();
}
}
Otherwise, if you need to do something after all threads have finished, you synchronize on a shared object, not on a thread.