How can I enforce my threads to run in order? - java

I'm trying to print the alphabet in order using threads. I got the letters printing but I'm having trouble getting them in the right order.
So I'm getting something like B,A,D,C
Is there a way to enforce the order of execution? I want thread 1 to go then wait, then thread 2, etc and then loop around again
Here is what I have:
public class Letters {
public static void main(String[] args) {
char[] arr1 = new char[]{'A', 'E', 'I', 'M', 'Q', 'U', 'Y'};
char[] arr2 = new char[]{'B', 'F', 'J', 'N', 'R', 'V', 'Z'};
char[] arr3 = new char[]{'C', 'G', 'K', 'O', 'S', 'W'};
char[] arr4 = new char[]{'D', 'H', 'L', 'P', 'T', 'X'};
mythread c1 = new mythread(arr1);
mythread c2 = new mythread(arr2);
mythread c3 = new mythread(arr3);
mythread c4 = new mythread(arr4);
Thread t1 = new Thread (c1);
Thread t2 = new Thread (c2);
Thread t3 = new Thread (c3);
Thread t4 = new Thread (c4);
t1.start();
t2.start();
t3.start();
t4.start();
}
static class mythread extends Thread{
char arr []; //= {'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'};
mythread () {};
mythread (char [] x) {
this.arr = x; // .arrcopy didn't work
}
public void run () {
try {
printletters(arr);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized void printletters(char [] arr) throws InterruptedException {
int q = 0;
for(int count = 0 ; count < arr.length; count++) {
System.out.println(arr[count]);
wait(10);
q++;
if(q >= 4) {
notifyAll();
q = 0;
}
}
}
}

To offer something other than what is already in the comments, here is a basic way to ensure that your threads run in order and will demonstrate one way to create custom synchronizers. A synchronizer is a means of controlling execution between threads.
There are many ways to solve this problem. For simplicity, 4 synchronization objects will be used. Each thread will 'block' on it's predecessor thread, print a letter, and when complete 'signal' its successor thread. The blocking and signalling is achieved by the synchronizer.
Here is the Synchronizer:
public class TSync {
private final Lock lock = new ReentrantLock();
private final Condition previousThreadDone = lock.newCondition();
private boolean ready = false; // Guarded by lock
public void waitForPreviousThread() throws InterruptedException {
lock.lock();
try {
while (!ready)
previousThreadDone.await();
ready = false;
} finally {
lock.unlock();
}
}
public void signalNextThread() {
lock.lock();
try {
ready = true;
previousThreadDone.signal();
} finally {
lock.unlock();
}
}
}
And now your Letters class which now uses the TSync class to co-ordinate the execution flow:
public class Letters {
public static void main(String[] args) {
char[] arr1 = new char[] { 'A', 'E', 'I', 'M', 'Q', 'U', 'Y' };
char[] arr2 = new char[] { 'B', 'F', 'J', 'N', 'R', 'V', 'Z' };
char[] arr3 = new char[] { 'C', 'G', 'K', 'O', 'S', 'W' };
char[] arr4 = new char[] { 'D', 'H', 'L', 'P', 'T', 'X' };
TSync sync1 = new TSync();
TSync sync2 = new TSync();
TSync sync3 = new TSync();
TSync sync4 = new TSync();
Mythread c1 = new Mythread(arr1, sync1, sync2);
Mythread c2 = new Mythread(arr2, sync2, sync3);
Mythread c3 = new Mythread(arr3, sync3, sync4);
Mythread c4 = new Mythread(arr4, sync4, sync1);
Thread t1 = new Thread(c1);
Thread t2 = new Thread(c2);
Thread t3 = new Thread(c3);
Thread t4 = new Thread(c4);
t1.start();
t2.start();
t3.start();
t4.start();
System.out.println("Signalling Thread 1 is ready to work");
sync1.signalNextThread();
}
}
class Mythread extends Thread {
private final char[] arr;
private final TSync waitOnSync;
private final TSync signalSync;
public Mythread(char[] arr, TSync waitOnSync, TSync signalSync) {
super();
this.arr = arr;
this.waitOnSync = waitOnSync;
this.signalSync = signalSync;
}
#Override
public void run() {
boolean isInterrupted = false;
for (int i=0; i<arr.length && !isInterrupted; i++) {
try {
waitOnSync.waitForPreviousThread();
System.out.println(arr[i]);
signalSync.signalNextThread();
} catch (InterruptedException e) {
isInterrupted = true;
}
}
}
}
Now the alphabet will print in order (i.e. the synchronizers have ensured that each thread will run in the order you wish).

Related

displaying the alphabet with arrays and methods [duplicate]

This question already has answers here:
Java arrays printing out weird numbers and text [duplicate]
(10 answers)
Closed 9 months ago.
package Exercises;
public class Challenge9 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//create class instance
Challenge9 al = new Challenge9();
//call the first method
//al.returnAlphabetArray();
//call second method
char[] A = al.getAlphabetArray();
System.out.println("The letters of the alphabet are: " + A);
}
//public void returnAlphabetArray() {
//System.out.println("Read the alphabet");
//}
public char[] getAlphabetArray() { //create first method
char[] letters = {'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'};
return letters;
}
}
I want to display the letters of the alphabet but why am I getting this output after the string: "[C#3d012ddd" ?
if you don't want to hard code the alphabet
public char[] getAlphabetArray() {
char[] letters = new char[122 - 97];
for (int i = 0; i < letters.length; i++) {
letters[i] = (char) (97 + i);
}
return letters;
}
And use this to print an array
Arrays.toString(getAlphabetArray())

Use insertion sort to sort vowels at the beginning of string

Is it possible to use insertion sort algorithm to sort the vowels at the beginning of a string?
I tried a lot but I don't get it , has somebody a hint how it could be implemented or should I use an other sort algorithm?
static char[] text = "thisIsAString".toCharArray();
static void instertionSort() {
for (int i = 0; i < text.length; i++) {
char h = text[i];
int j = i - 1;
while ((j >= 0) && Character.toLowerCase(text[j]) > Character.toLowerCase(h)) {
text[j+1] = text[j];
j = j - 1;
}
text[j+1] = h;
}
}
Example: "thisIsAString" -> "AiiIghnrssStt"
You can use insertion sort for this (just like every other sort-algorithm, they are all equal. Only the time they take for sorting the field is different, but the result is always the same).
The problem in your algorithm is that you don't check whether the compared characters are vowels or upper/lower case.
This code should work:
public class StringSorter {
private static final String vowels = "aeiou";
public static void main(String[] args) {
char[] string = "thisIsAString".toCharArray();
char[] test2 = "thisIsAStringaAabBs".toCharArray();
System.out.println("unsorted: " + new String(string));
insertionSort(string);
System.out.println("sorted: " + new String(string));
System.out.println();
System.out.println("unsorted: " + new String(test2));
insertionSort(test2);
System.out.println("sorted: " + new String(test2));
}
public static void insertionSort(char[] string) {
for (int i = 1; i < string.length; i++) {
char h = string[i];
int j = i;
while ((j > 0) && isBefore(string[j - 1], h)) {
string[j] = string[j - 1];
j = j - 1;
}
string[j] = h;
}
}
private static boolean isBefore(char a, char b) {
String lowA = Character.toString(Character.toLowerCase(a));
String lowB = Character.toString(Character.toLowerCase(b));
if (vowels.contains(lowA)) {
if (vowels.contains(lowB)) {
//both are vowels
return chooseLowerCaseFirst(a, b);
}
else {
//only a is a vowel
return false;
}
}
else if (vowels.contains(lowB)) {
//only b is a vowel
return true;
}
else {
//none is a vowel
return chooseLowerCaseFirst(a, b);
}
}
private static boolean chooseLowerCaseFirst(char a, char b) {
String lowA = Character.toString(Character.toLowerCase(a));
String lowB = Character.toString(Character.toLowerCase(b));
if (lowA.equals(lowB)) {
//both are the same character
if (Character.isLowerCase(a)) {
if (Character.isLowerCase(b)) {
//both are lower case
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
else {
//only a is lower case
return false;
}
}
else if (Character.isLowerCase(b)) {
//only b is lower case
return true;
}
else {
//both are upper case
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
}
else {
//different characters
return Character.toLowerCase(a) > Character.toLowerCase(b);
}
}
}
The output that is generated is:
unsorted: thisIsAString
sorted: AiiIghnrssStt
unsorted: thisIsAStringaAabBs
sorted: aaAAiiIbBghnrsssStt
If you are considering other methods too, from Java 8 you can do it by mixing streams and comparators.
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private static List<Character> order = new ArrayList<>(Arrays.asList('a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U', 'b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'h', 'H', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z'));
public static void main(String[] args) {
String example = "thisIsAString";
List<Character> cl = example.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
List<Character> ls = cl.stream().sorted(Comparator.comparingInt(order::indexOf)).collect(Collectors.toCollection(ArrayList::new));
StringBuilder result = new StringBuilder();
for (Character c : ls) result.append(c);
System.out.println(result);
}
}

print alphabets and numbers using two threads one at a time

I am working on below interview question where I need to print out alphabet and numbers using two threads. One prints alphabets (a,b,c...z) and other prints numbers(1,2,3....26). Now I have to implement it in such a way that the output should be:
a
1
b
2
...
...
z
26
So I came up with below code one without synchronization but for some reason it is not printing last alphabet which is z
class Output {
private static final int MAX = 26;
private static int count = 1;
private static final Queue<Character> queue = new LinkedList<>(Arrays.asList(new Character[] {
'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'}));
private boolean isAlphabet = true;
public void printAlphabet() {
while (true) {
if (count > MAX)
break;
if (!isAlphabet) {
System.err.println(Thread.currentThread().getName() + " : " + queue.remove());
isAlphabet = true;
}
}
}
public void printNumber() {
while (true) {
if (count > MAX)
break;
if (isAlphabet) {
System.err.println(Thread.currentThread().getName() + " : " + count++);
isAlphabet = false;
}
}
}
}
public class PrintAlphabetNumber {
public static void main(String[] args) {
Output p = new Output();
Thread t1 = new Thread(() -> p.printAlphabet());
t1.setName("Alphabet");
Thread t2 = new Thread(() -> p.printNumber());
t2.setName("Number");
t1.start();
t2.start();
}
}
Is there any issue in my above code? Also from synchronization perspective, does it look good or not?
for some reason it is not printing last alphabet which is z
You abort when count > MAX, which is true after the last number.
After the last number, you're supposed to print the last letter, but now count > MAX so it's already stopping.
from synchronization perspective, does it look good or not?
No, this does not look good.
You are using a spinlock. This is very inefficient as both loops use 100% CPU constantly, whether they have work to do or not. It's also not guaranteed to work with non-volatile lock variables.
The classic Java solution would use wait()/notify().
like they said this is not good code for doing this, but the issue with this code is that you got the if condition backwards.
public void printAlphabet() {
while (true) {
if (count > MAX)
break;
if (isAlphabet) {// this was !isAlphabet
System.err.println(Thread.currentThread().getName() + " : " + queue.remove());
isAlphabet = false;//also here
}
}
}
public void printNumber() {
while (true) {
if (count > MAX)
break;
if (!isAlphabet) {// this was isAlphabet
System.err.println(Thread.currentThread().getName() + " : " + count++);
isAlphabet = true;//also here
}
}
}

Java For Loop Ignores i Position when Letter of Array is the Same

import java.util.Scanner;
import java.lang.*;
public class testing {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
char[] engArray = {'A','B','C','D','E','F','G','H','I'};
String stringEngArray = String.valueOf(engArray);
System.out.println("Text input");
String input2 = input.nextLine().toUpperCase();
int inputedOffset = 4;
char[] finalArray = inpute2.toCharArray();
for (int i = 0; i < inputedText.length(); i++) {
int arrayPosition = inpute2.indexOf(inputedText.charAt(i));
int engPosition = stringEngArray.indexOf(inputedText.charAt(i));
int test = (arrayPosition % inputedOffset);
int newTest = engPosition+test;
finalArray[i] = engArray[newTest];
}
String output = new String(finalArray);
System.out.println(output);
}
}
I am trying to change the inputted by user text in order to accomplish some basic encryption.
When i enter abcd or tesla or world the output works as expected and is changing to aceg to tfuoa to wptod
The problem occurs when i am entering aaaa or aabbcc or generally when a letter is repeated on the text. At the second time the for loop finds the same letter it just uses the array position of the 1st read similar letter.
Any idea?
This happens because inputedText.indexOf(inputedText.charAt(i));, this is what's causing it to return the same index, since it will just grab the first occurance of a which will be the same for every a character.
You're trying to get the array position, but why are you doing it this way when the arrayposition is already the variable i?
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
char[] engArray = { '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' };
String stringEngArray = String.valueOf(engArray);
System.out.println("Text input");
String inputedText = input.nextLine().toUpperCase();
int inputedOffset = 4;
char[] finalArray = inputedText.toCharArray();
for (int i = 0; i < inputedText.length(); i++) {
int engPosition = stringEngArray.indexOf(inputedText.charAt(i));
int test = (i % inputedOffset);
int newTest = engPosition + test;
finalArray[i] = engArray[newTest];
}
String output = new String(finalArray);
System.out.println(output);
}
You are using indexOf() to get the arrayposition. This will always return the position of the first occurrence of that character in the string.
You can simply use i as the arrayposition.

MorseCode class not translating

This program is supposed to translate English into morse code, but every time i input a word I get English letters and numbers such as "\cf0" for hi. I am pretty sure the morse code array has the right values. Could it be a formatting problem? PLease help. thanks.
MorseCode class
public class MorseCode {
public static String decode(char[] alphabet, String[] morseCode, String originalMessage) {
char currentChar;
String getMorseChar;
String convertedString = " ";
for (int i = 0; i < originalMessage.length(); i++) {
convertedString = " ";
currentChar = originalMessage.charAt(i);
getMorseChar = convert(currentChar, alphabet, morseCode);
convertedString = convertedString + getMorseChar;
}
return convertedString;
}
public static String convert (char currentChar, char[] alphabet, String[] morseCode) {
String morse = "";
for (int x = 0; x < alphabet.length; x++) {
if (currentChar == alphabet[x])
morse = morseCode[x];
}
return morse;
}
}
MorseCodeTester class
public class MorseCodeTester {
public static void main(String[] args) throws IOException {
String[] morseCode = new String[26];
char[] alphabet = { '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' };
Scanner scanner = new Scanner(System.in);
Scanner inFile = new Scanner(new File("morse.rtf"));
for (int x = 0; x < 26; x++) {
morseCode[x] = inFile.next( );
}
inFile.close();
System.out.println("What message would you like to translate?");
String originalMessage = scanner.next();
String converted = MorseCode.decode(alphabet, morseCode, originalMessage);
System.out.println(converted);
}
}

Categories