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!
CodePudding user response:
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
CodePudding user response:
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) {
mutex.notify();
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