2 Threads taking turns printing the alphabet [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am supposed to write code for an assignment. The goal is to make 2 threads (which are objects of a class that implements runnable) take turns printing the alphabet. One of them prints upper case while the other one prints lower case.
(they print only a single letter each turn, not the whole alphabet, just for clarification)
I feel like my code is pretty self-explainatory but if I am wrong here and you have questions please ask them! I appreciate any help I can get for sure!
The Code:
public class ABCPrinter implements Runnable {
// --- Attributes ---
private boolean bool_isUpperCase;
public boolean bool_Switch = true;
// --- Constructor ---
public ABCPrinter (boolean init_isUpperCase) {
this.bool_isUpperCase = init_isUpperCase;
}
#Override
public synchronized void run() { // custom run method
for (char char_Counter = 'a'; char_Counter <= 'z'; char_Counter++) { // count through the alphabet
if (bool_isUpperCase){ // decide whether to print upper or lower case
if(bool_Switch) {
System.out.println(Character.toUpperCase(char_Counter));
System.out.println("\n----------------------");
System.out.println("Message has been sent.");
System.out.println("-----------------------");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("\nInterrupted.");
}
bool_Switch = false;
System.out.println("\n--------------------");
System.out.println("Switch has been set to false.");
System.out.println("-----------------------");
try {
Thread.sleep(10000);
notifyAll();
System.out.println("\n--------------------");
System.out.println("All threads have been notified.");
System.out.println("-----------------------");
Thread.sleep(10000);
wait();
System.out.println("\n--------------------");
System.out.println("Thread 1 is waiting.");
System.out.println("-----------------------");
} catch (Exception e) {
System.out.println("Process Interrupted.");
}
} else {
try {
System.out.println("Thread 1 is waiting.");
wait();
} catch (Exception e) {
System.out.println("Process Interrupted.");
}
}
} else {
if(!bool_Switch) {
System.out.println(Character.toUpperCase(char_Counter));
System.out.println("\n----------------------");
System.out.println("Message has been sent.");
System.out.println("-----------------------");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("\nInterrupted.");
}
bool_Switch = true;
System.out.println("\n--------------------");
System.out.println("Switch has been set to true.");
System.out.println("-----------------------");
try {
Thread.sleep(1000);
notifyAll();
System.out.println("\n--------------------");
System.out.println("All threads have been notified.");
System.out.println("-----------------------");
Thread.sleep(1000);
wait();
System.out.println("\n--------------------");
System.out.println("Thread 2 is waiting.");
System.out.println("-----------------------");
} catch (Exception e) {
System.out.println("Process Interrupted.");
}
} else {
try {
System.out.println("Thread 2 is waiting.");
wait();
} catch (Exception e) {
System.out.println("Process Interrupted.");
}
}
}
}
}
}
Here is the main method where everything is executed:
public class Main2 {
public boolean bool_switch;
public static void main(String[] args){
ABCPrinter p1 = new ABCPrinter(true);
ABCPrinter p2 = new ABCPrinter(false);
Thread thr_UpperCase = new Thread(p1);
Thread thr_LowerCase = new Thread(p2);
thr_UpperCase.start();
thr_LowerCase.start();
}
}
Like I said I appreciate any help or advice for improvement. I would first and foremost love to get it to work though, been stuck at this assignment for 2 days now.
Have a good one!

This new answer involves the usage of wait and notify as requested by you.The main function changed a little to include a mutex Object that is used for synchronization:
Main:
public class Main2 {
public static void main(String[] args) throws InterruptedException {
// Mutex object that will serve as a lock
final Object mutex = new Object();
ABCPrinter p1 = new ABCPrinter(mutex, true);
ABCPrinter p2 = new ABCPrinter(mutex, false);
final Thread thr_UpperCase = new Thread(p1);
final Thread thr_LowerCase = new Thread(p2);
thr_LowerCase.start();
thr_UpperCase.start();
thr_LowerCase.join();
thr_UpperCase.join();
}
}
ABC Printer:
public class ABCPrinter implements Runnable {
private final Object mutex;
private static char currentChar;
private final boolean printUpperCaseBoolean;
static {
currentChar = 'a';
}
public ABCPrinter(final Object mutex, final boolean printUpperCaseBoolean) {
this.mutex = mutex;
this.printUpperCaseBoolean = printUpperCaseBoolean;
}
#Override
public void run() {
while (currentChar <= 'z') {
if (printUpperCaseBoolean) {
try {
synchronized (mutex) {
System.out.println(Character.toUpperCase(currentChar));
currentChar++;
mutex.wait();
}
}
catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
else {
try {
// Wait so that this thread can't start directly again
Thread.sleep(100);
synchronized (mutex) {
System.out.println(currentChar);
currentChar++;
mutex.notify();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
This prints:
A
b
C
d
E
f
G
h
I
j
K
l
M
n
O
p
Q
r
S
t
U
v
W
x
Y
z

If you work with concurrencies and Threads. The class Semaphore is actually pretty helpful. I used the Producer-Consumer Pattern to solve your problem.Also keep in mind to use the join function in your Main.
Main:
public class Main2 {
public static void main(String[] args) throws InterruptedException {
ABCPrinter p1 = new ABCPrinter(true);
ABCPrinter p2 = new ABCPrinter(false);
final Thread thr_UpperCase = new Thread(p1);
final Thread thr_LowerCase = new Thread(p2);
thr_LowerCase.start();
thr_UpperCase.start();
thr_LowerCase.join();
thr_UpperCase.join();
}
}
import java.util.concurrent.Semaphore;
public class ABCPrinter implements Runnable {
private final boolean printUpperCaseBoolean;
private static final Semaphore FREE_SEMAPHORE;
private static final Semaphore WORK_SEMAPHORE;
private static final Semaphore MUTEX_SEMAPHORE;
static{
FREE_SEMAPHORE = new Semaphore(0);
WORK_SEMAPHORE = new Semaphore(1);
MUTEX_SEMAPHORE = new Semaphore(2);
}
public ABCPrinter(final boolean printUpperCaseBoolean) {
this.printUpperCaseBoolean = printUpperCaseBoolean;
}
#Override
public void run() {
for (char char_Counter = 'a'; char_Counter <= 'z'; char_Counter++) { // count through the alphabet
if(printUpperCaseBoolean){
try{
WORK_SEMAPHORE.acquire();
MUTEX_SEMAPHORE.acquire();
System.out.println(Character.toUpperCase(char_Counter));
MUTEX_SEMAPHORE.release();
FREE_SEMAPHORE.release();
}
catch (InterruptedException ex){
ex.printStackTrace();
}
}else{
try {
FREE_SEMAPHORE.acquire();
MUTEX_SEMAPHORE.acquire();
System.out.println(char_Counter);
MUTEX_SEMAPHORE.release();
WORK_SEMAPHORE.release();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The output looks like:
A
a
B
b
C
c
D
d
E
e
F
f
G
g
H
h
I
i
J
j
K
k
L
l
M
m
N
n
O
o
P
p
Q
q
R
r
S
s
T
t
U
u
V
v
W
w
X
x
Y
y
Z
z

Related

Why Producer-Consumer code is not working?

I am trying to code solution of Producer-Consumer problem with the help of Semaphores.
Below is the code I have written, on execution it is getting stuck after producing one number.
I have checked the assignment of both the Semaphore and it look fine.
The sequence of acquire and release methods being called also looks correct.
public class Q {
int n;
Semaphore consumerSem = new Semaphore(0);
Semaphore producerSem = new Semaphore(1);
synchronized void get(){
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Got Data : " + n);
producerSem.release();
}
synchronized void put(int n){
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Putting Data : " + n);
this.n=n;
consumerSem.release();
}
}
public class Producer implements Runnable{
Q q;
Producer(Q q){
this.q = q;
}
#Override
public void run() {
for (int i=0; i<20;i++){
q.put(i);
}
}
}
public class Consumer implements Runnable{
Q q;
Consumer(Q q){
this.q = q;
}
#Override
public void run() {
for (int i =0;i<20;i++){
q.get();
}
}
}
public class PCRun {
public static void main(String[] args) {
Q q = new Q();
new Thread(new Producer(q),"Producer").start();
new Thread(new Consumer(q),"Consumer").start();
}
}
You've made get and put synchronized. So the producer goes in, locks q, uses the one permit of producerSem and blocks at the next put call. Unfortunately, q is still locked by the producer, so the consumer won't be able to enter get. To fix this, remove both synchronizeds.
Now to synchronize the access on n, use synchronized only where n is accessed, not for both whole methods.
int n;
final Semaphore consumerSem = new Semaphore(0);
final Semaphore producerSem = new Semaphore(1);
void get() {
try {
consumerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
System.out.println("Got Data : " + n);
}
producerSem.release();
}
void put(int n) {
try {
producerSem.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) { // invariant print + write, atomic
System.out.println("Putting Data : " + n);
this.n = n;
}
consumerSem.release();
}
Instead of using 2 semaphores, only use 1. The value of n will ultimately be shared among 2 threads so it's the only thing that needs to be synchronized because Semaphores are inherently thread-safe.
public static class Q {
int n;
Semaphore available = new Semaphore(0);
void get() throws InterruptedException {
available.acquire();
synchronized (this) {
System.out.printf("Get %s\n", n));
}
}
void put(int n){
available.release();
synchronized (this) {
System.out.printf("Put %s\n", n);
this.n = n;
}
}
}

Multithreading: How to get a thread to execute more frequently than the others?

I've recently been learning about semaphores to specify the ordering of threads, but I'm curious about how to control the frequency as well. Below is a program that prints *, a digit, and then a letter to the screen. Always in that order (e.g. *1A). How can I make it so certain threads print more than once before the others? (e.g. *32A)
import java.lang.Thread;
import java.util.concurrent.*;
public class ThreadSync {
private static boolean runFlag = true;
private static Semaphore canPrintSymbol = new Semaphore(1);
private static Semaphore canPrintDigit = new Semaphore(0);
private static Semaphore canPrintLetter = new Semaphore(0);
public static void main( String[] args ) {
Runnable[] tasks = new Runnable[17];
Thread[] threads = new Thread[17];
// Create 10-digit threads
for (int d = 0; d < 10; d++) {
tasks[d] = new PrintDigit((char)('0' + d));
threads[d] = new Thread(tasks[d]);
threads[d].start();
}
// Create 6-letter threads
for (int d = 0; d < 6; d++) {
tasks[d + 10] = new PrintLetter((char)('A' + d));
threads[d + 10] = new Thread(tasks[d + 10]);
threads[d + 10].start();
}
// Create a thread to print asterisk
tasks[16] = new PrintSymbol('*');
threads[16] = new Thread(tasks[16]);
threads[16].start();
// Let the threads run for a period of time
try { Thread.sleep(500); }
catch (InterruptedException ex) { ex.printStackTrace(); }
runFlag = false;
// Interrupt the threads
for (int i = 0; i < 17; i++) threads[i].interrupt();
}
public static class PrintSymbol implements Runnable {
private char c;
public PrintSymbol(char c) {
this.c = c;
}
public void run() {
while (runFlag) {
try {
canPrintSymbol.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintDigit.release();
}
}
}
public static class PrintDigit implements Runnable {
private char c;
public PrintDigit(char c) { this.c=c; }
public void run() {
while (runFlag) {
try {
canPrintDigit.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintLetter.release();
}
}
}
public static class PrintLetter implements Runnable {
private char c;
public PrintLetter(char c) {
this.c = c;
}
public void run() {
while (runFlag) {
try {
canPrintLetter.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%c\n", c);
canPrintSymbol.release();
}
}
}
}
Short answer is you can't. At least not to my knowledge. There are hints you can give to the OS like yielding your thread. This means it yields it processing to the next thread. Other then that all you can really do is influence the priority. But all these are just hints to the OS. The OS ultimately determines the order in which the threads are executed. This is one of the main things to keep in mind when working with multiple threads. It is generally not a good idea to have a dependency between separate threads which makes the order of execution important.

Cyclic Barrier in java

I have a list which needs to be populated by three parties(threads,lets say).I am using cyclic barrier to achieve this functionality. Everything works fine except that I am not able to use the resulted list without inducing a forced sleep. Below is the code :
public class Test{
List<Integer> item = new Vector<Integer>();
public void returnTheList(){
CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
#Override
public void run() {
System.out.println("All parties are arrived at barrier, lets play -- : " + CyclicBarrierTest.getTheList().size());
//Here I am able to access my resulted list
}
});
CyclicBarrierTest sw1 = new CyclicBarrierTest(cb, new ZetaCode(1500), s);
CyclicBarrierTest sw2 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
CyclicBarrierTest sw3 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
Thread th1 = new Thread(sw1, "ZetaCode1");
Thread th2 = new Thread(sw2, "ZetaCode2");
Thread th3 = new Thread(sw3, "ZetaCode3");
th1.start();
th2.start();
th3.start();
}
public static void main(String args[]){
System.out.println("asdfasd");
Test test = new Test();
//ActionClass ac = new ActionClass();
test.returnTheList();
System.out.println("Inside the main method...size of the final list : " +test.item.size() );
}
Below is my CyclicBrrierTest class :
public class CyclicBarrierTest implements Runnable{
private CyclicBarrier barrier;
private Object obj;
static volatile String s = "";
volatile List<Integer> finalIntList = new Vector<Integer>();
public CyclicBarrierTest(CyclicBarrier barrier, Object obj, String s){
this.barrier = barrier;
this.obj = obj;
}
#Override
public void run(){
try{
System.out.println(Thread.currentThread().getName() + " is waiting on barrier and s is now : " + finalIntList.size());
ZetaCode simple = (ZetaCode)obj;
finalIntList.addAll(simple.getTheItemList());
barrier.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
}catch(InterruptedException ex){
System.out.println("Error.." + ex.getMessage());
}catch(Exception e){
System.out.println("Error.." + e.getMessage());
}
}
public List<Integer> getTheList(){
return finalIntList;
}
So if I run this code without giving any delay the print statement in my main method gives me the length of my list as zero,however after giving an appropriate sleep it gives me the expected output.I want to achieve the same without giving any delay.Any help would be appreciated.
Thanks in advance.
It seems you'd want to use a CountDownLatch, not a CyclicBarrier here. The CyclicBarrier is working exactly as intended - your main method just isn't waiting for it to be tripped by all 3 threads. When you give it a sleep statement, the other 3 threads just happen to finish before main wakes up again.
A CyclicBarrier is useful when you need N workers to all reach the same 'checkpoint' before proceeding, and the workers themselves are the only ones who care. However, you have an N + 1 user here, the main thread, who wants to know when they're all done, and CyclicBarrier doesn't support that use case.
Note, of course that you can also use both of them.
In this code we have 4 tasks . Task1, Task2, Task3 producing int values and Task4 will add all the int values . Task4 is waiting after calling await() for Task1, Task2, Task3 to produce values.When they produce values they call await() method and Task 4 will add their values and print the o/p and call reset() method so the barrier will reset. After reset this process will continue again
package practice;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicbarrierExample {
public static void main(String[] args) {
CyclicBarrier c = new CyclicBarrier(4);
Task1 t1 = new Task1(c);
Task2 t2 = new Task2(c);
Task3 t3 = new Task3(c);
Task4 t4 = new Task4(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Task1 extends Thread {
CyclicBarrier c;
static int t1 ;
public Task1(CyclicBarrier c) {
this.c = c;
}
#Override
public void run() {
while (true) {
t1 = t1 + 1;
try {
c.await();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Task2 extends Thread {
CyclicBarrier c;
static int t2;
public Task2(CyclicBarrier c) {
this.c = c;
}
#Override
public void run() {
while (true) {
t2 = t2 + 1;
try {
c.await();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
class Task3 extends Thread {
CyclicBarrier c;
static int t3;
public Task3(CyclicBarrier c) {
this.c = c;
}
#Override
public void run() {
while (true) {
t3 = t3 + 1;
try {
c.await();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
class Task4 extends Thread {
CyclicBarrier c;
static int t4;
static int count=0;
public Task4(CyclicBarrier c) {
this.c = c;
}
#Override
public void run() {
while (count<10) {
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
t4 = Task1.t1 + Task2.t2 + Task3.t3;
System.out.println(t4);
try {
c.reset();
} catch (Exception e) {
System.out.println("yo");
}
count++;
}
}
}

java synchronization and starvation

i have made a program and expecting output like this :
A
1
a
B
2
b
C
3
c
...
E
5
e
here is my code i think am getting starvation problem plz help me
class Product {
static boolean flag1, flag2, flag3;
synchronized void printLwrAlpha(char value) {
// System.out.println(flag3+": inside lwr_alpha");
if (!flag3)
try {
wait();
} catch (Exception ex) {
System.out.println(ex);
}
System.out.println(value);
flag3 = false;
flag1 = false;
System.out.println("before notify");
notify();
System.out.println("after notify");
}
synchronized void printUprAlpha(char n) {
// System.out.println(flag1+": inside upr_alpha");
if (flag1)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
System.out.println(n);
// System.out.println(num);
flag1 = true;
flag2 = true;
notify();
}
synchronized void printNum(int num) {
// System.out.println(flag2+": inside num");
if (!flag2)
try {
wait();
} catch (Exception e) {
System.out.println(e);
}
// System.out.println(n);
System.out.println(num);
flag2 = false;
flag3 = true;
notify();
}
}
class PrintNum implements Runnable {
Product p;
PrintNum(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++)
p.printNum(i);
}
}
class PrintLwrAlpha implements Runnable {
Product p;
static char ch = 'a';
PrintLwrAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printLwrAlpha(c);
}
}
}
class PrintUprAlpha implements Runnable {
Product p;
static char ch = 'A';
PrintUprAlpha(Product p) {
this.p = p;
new Thread(this, "Producer").start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void run() {
for (int i = 1; i <= 5; i++) {
char c = (char) (ch + (i - 1));
p.printUprAlpha(c);
}
}
}
public class MainClass1 {
public static void main(String ar[]) {
Product p = new Product();
new PrintNum(p);
new PrintUprAlpha(p);
new PrintLwrAlpha(p);
}
}
i am getting this output:
run:
A
1
B
2
C
3
D
4
E
5
a
before notify
after notify
i think after this program is going in to starvation
Replace all your ifs, e.g.
if (!flag3)
with while loops
while (!flag3)
If I understand correctly your problem is that you're trying to use a single wait object with multiple threads. The common scenario for wait/notify is as follows: the one thread is waiting for resource to become available while the second thread produces the resource and notifies the first thread.
In code it may look like this:
class ResourceFactory {
public synchronized void produce()
{
// make the resource available
obj.notify();
}
public synchronized void consume()
{
if( /* resource is not available */ ) {
obj.wait();
}
// do something with resource
}
}
When multiple threads are trying to wait on a single object the problem is that it's up to implementation which thread would be awaken after notify call. I think you should make 3 different objects and do something like this:
// thread 1
obj1.wait();
obj2.notify()
// thread 2
obj2.wait();
obj3.notify()
// thread 3
obj3.wait();
obj1.notify()
Be careful and try not to deadlock your code.
And at last your code. First two threads are waiting and awaken each other despite the flags. And when the third thread is awaken there's no thread to notify it. So it's a classical deadlock.

Java - multithreading and synchronization

I have two very similar programs each trying to run two threads OddThread and EvenThread and trying to print the odd and even numbers in sequence . While the first one works , the second one hangs . Can anyone please pinpoint the bug in the second program ?
The first one which works :
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Odd Even test");
NumHolder objNumHolder = new NumHolder();
Odd o1 = new Odd(objNumHolder, "Odd Number Thread");
Even e1 = new Even(objNumHolder, "Even Number Thread");
o1.start();
e1.start();
}
}
class NumHolder {
private int intCurrNum;
private boolean isEven = false;
public synchronized void printOddNumber(String tname) {
while (isEven == true){
try {
wait();
}catch (InterruptedException e) {
}
}
isEven = true;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
public synchronized void printEvenNumber(String tname) {
while (isEven == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
isEven = false;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
class Even extends Thread {
private NumHolder objNumHolder;
public Even(NumHolder p_objNumHolder, String name) {
super(name);
objNumHolder=p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printEvenNumber(getName());
}
}
}
class Odd extends Thread {
private NumHolder objNumHolder;
public Odd(NumHolder p_objNumHolder,String name) {
super(name);
objNumHolder = p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printOddNumber(getName());
}
}
}
The second code which hangs :
class PrintClass {
int intCurrNum;
private boolean isEven = false;
synchronized void printOdd(){
while(isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printOdd()");
ie.printStackTrace();
}
isEven = true;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
synchronized void printEven(){
while(!isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printEven()");
ie.printStackTrace();
}
isEven = false;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
}
class ThreadOdd extends Thread {
PrintClass pc = null;
ThreadOdd(PrintClass pc , String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printOdd();
}
}
}
class ThreadEven extends Thread {
PrintClass pc = null;
ThreadEven(PrintClass pc,String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printEven();
}
}
}
public class EvenOddPrintClass {
public static void main(String[] args){
PrintClass pc = new PrintClass();
Thread to = new ThreadOdd(pc,"ThreadOdd");
Thread te = new ThreadEven(pc,"ThreadEven");
to.start();
te.start();
}
}
Thanks.
I suggest you run your code in the debugger and step through both threads. It's very educational. You will see exactly where the error is.
In both versions, isEven starts out as false.
In the first version, printOddNumber will skip the whole while loop, print the odd number, set isEven to true and notify the even thread, which will print the even number and notify the odd thread again etc. in sequence.
In the second version, printOddNumber will skip the whole while loop, including printing the number and notifying the even thread. After 10 attempts it will exit without having printed anything, and leaving the even thread hanging without ever having notified it.
Interesting. So initially the isEven = false. If the printOdd() is called first then the while (isEven) test is false so printOdd() will exit immediately without generating any output. The while loops in your first program only encompass the wait test, not the entire method.
Then when printEven() is called by the other thread, it will call wait() and hang since there is no other thread to call notifyAll().
You only should want the while loop around the wait since you are going to exit after you print out the even or odd number anyway, right? So the logic in the first program is correct.
public class CountDownApp
{
public static void main(String[] args)
{
Thread count1 = new CountDownEven();
Thread count2 = new CountDownOdd();
count1.start();
count2.start();
}
}
class CountDownEven extends Thread
{
public void run()
{
for(int i=10;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class CountDownOdd extends Thread
{
public void run()
{
for(int i=9;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Categories

Resources