I'm working on a problem where I have to use 4 different threads to write out a LETTER event INTERNAL ms AMOUNT times. The first 3 threads start right away the forth one is awaiting for one of them to finish & then starting.
I have got the code to a point where is doing what it should although the code is not "ending" it's actively waiting.
Could you advise what could be the issue here?
public class PrinterThread extends Thread {
private String letter;
private int internal;
private int amount;
public PrinterThread(String letter, int internal, int amount){
this.letter = letter;
this.internal = internal;
this.amount = amount;
}
public void run(){
for (int i = 1; i <= amount; i++) {
System.out.println(letter);
try {
Thread.sleep(internal);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
PrinterThread printerThread = new PrinterThread("A", 1, 1000);
PrinterThread printerThread1 = new PrinterThread("B", 1, 1000);
PrinterThread printerThread2 = new PrinterThread("C", 1, 1);
PrinterThread printerThread3 = new PrinterThread("D", 5, 50);
printerThread.start();
printerThread1.start();
printerThread2.start();
while(!printerThread3.isAlive()){
if (!printerThread.isAlive() || !printerThread1.isAlive() || !printerThread2.isAlive()) {
printerThread3.start();
}
}
}
}
Break out of the while loop, once you have started printerThread3.
public class PrinterThread extends Thread {
private String letter;
private int internal;
private int amount;
public PrinterThread(String letter, int internal, int amount){
this.letter = letter;
this.internal = internal;
this.amount = amount;
}
public void run(){
for (int i = 1; i <= amount; i++) {
System.out.println(letter);
try {
Thread.sleep(internal);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
PrinterThread printerThread = new PrinterThread("A", 1, 1000);
PrinterThread printerThread1 = new PrinterThread("B", 1, 1000);
PrinterThread printerThread2 = new PrinterThread("C", 1, 1);
PrinterThread printerThread3 = new PrinterThread("D", 5, 50);
printerThread.start();
printerThread1.start();
printerThread2.start();
while(!printerThread3.isAlive()){
if (!printerThread.isAlive() || !printerThread1.isAlive() || !printerThread2.isAlive()) {
printerThread3.start();
break;
}
}
//If you want main to wait for all the others to complete, then add this...
printerThread.join();
printerThread1.join();
printerThread2.join();
printerThread3.join();
}
}
Related
I've implemented a thread that get user input by keyboard. However, when user sets input my program returns an IllegalThreadStateException error, at line 23.
import java.util.Scanner;
public class Main {
static MyThread myThread = new MyThread();
static public boolean answered = false;
public static void main(String[] args) {
String s = "";
while (!s.equalsIgnoreCase("q")) {
int seconds = 0, average = 5;
if (seconds > average) {
myThread.stop();
String phrase = choosePhrase(seconds, average);
System.out.println(phrase);
Scanner keyboard = new Scanner(System.in);
s = keyboard.nextLine();
} else {
long createdMillis = System.currentTimeMillis();
myThread.start();
while (!answered && seconds < average) {
long nowMillis = System.currentTimeMillis();
seconds = (int) ((nowMillis - createdMillis) / 1000);
}
}
}
}
private static String choosePhrase(int seconds, int average) {
if (seconds > average + 10) {
return "¿D?";
} else if (seconds > average + 5) {
return "¿E?";
} else {
return "¿F?";
}
}
}
class MyThread extends Thread {
static String[] questions = {"¿A?", "¿B?", "¿C?"};
public void run() {
System.out.println("MyThread running");
Double d = Math.random() * 100;
int n = (int) (Math.ceil(d) % 3);
String question = questions[n];
System.out.println(question);
Scanner keyboard = new Scanner(System.in);
String s = keyboard.nextLine();
stop();
}
}
Why am I getting this exception? How do I make the thread gets and exits correctly to main function?
To make a thread exits proprely you have to use myThread.interrupt();
I've solved the issue with your suggestions:
import javax.swing.JOptionPane;
public class Main {
public static void main(String[] args) {
Latency latency = new Latency();
latency.start();
}
}
class Latency {
int seconds = 0, average = 5;
MyThread myThread;
ObjectToPass o = new ObjectToPass();
public void start() {
String s = "";
Thread t = null;
while (!s.equalsIgnoreCase("q")) {
// The program has just begun, or user has answered a question,
// or term has expired.
seconds = 0;
if (myThread != null) {
myThread.shutdown();
myThread = null;
}
if (o.answered) {
o.answered = false;
myThread = new MyThread(o, new String[]{"¿A?", "¿B?", "¿C?"});
} else {
myThread = new MyThread(o, new String[]{"¿D?", "¿E?", "¿F?"});
}
t = new Thread(myThread);
t.start();
long createdMillis = System.currentTimeMillis();
while (!this.o.getPlay() && seconds < average) {
long nowMillis = System.currentTimeMillis();
seconds = (int) ((nowMillis - createdMillis) / 1000);
}
}
}
}
class ObjectToPass {
boolean answered = true;
public synchronized boolean getPlay() {
return answered;
}
public synchronized void setPlay(boolean answered) {
this.answered = answered;
}
}
class MyThread implements Runnable {
ObjectToPass o;
static String[] questions;
public MyThread(ObjectToPass o, String[] questions) {
this.o = o;
this.questions = questions;
}
public void run() {
// System.out.println("MyThread running");
Double d = Math.random() * 100;
int n = (int) (Math.ceil(d) % 3);
String question = questions[n];
System.out.println(question);
// Scanner keyboard = new Scanner(System.in);
// String s = keyboard.nextLine();
Object[] options = {"Yes", "No"};
int oo = JOptionPane.showOptionDialog(null,
question, "Question", JOptionPane.YES_OPTION,
JOptionPane.NO_OPTION, null, options, options[0]);
this.o.setPlay(true);
}
public void shutdown() {
Thread.currentThread().interrupt();
return;
}
}
I have been writing a race code for a class I am in that races two threads, a tortoise and a hare. I can get both of them to run for 80 units but I don't know how to write a code that determines and outputs who the winner is. Any help would be appreciated because I am super new to coding.
I have the tortoise, hare, and raceParticipant classes. My driver class looks like this, where I would assume I put the winner code?
package Domain;
public class Driver
{
public static void main(String[] args)
{
Hare bob = new Hare();
Tortoise fred = new Tortoise();
int winDistance = 80;
do {
bob.sprint();
fred.sprint();
bob.display();
fred.display();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(bob.getTotalDistance() < winDistance && fred.getTotalDistance() < winDistance);
}
}
My sprint method is
public int sprint()
{
int sleep = generator.nextInt(100);
int sprintDistance = 0;
if (sleep > sleepPercent)
{
sprintDistance = generator.nextInt(topSpeed) + 1;
}
totalDistance +=sprintDistance;
return sprintDistance;
}
I don't see you creating a new thread anywhere.
You can create a Hare class like this:
public class Hare implements Runnable {
private static final int SLEEP_DURATION = 3000; //milliseconds
private static final int SPEED = 3; //units per second
private int distanceToRun;
private final RaceFinishListener listener;
public Hare(int distanceToRun, RaceFinishListener listener) {
this.distanceToRun = distanceToRun;
this.listener = listener;
}
#Override
public void run() {
do {
distanceToRun -= SPEED;
try {
Thread.sleep(SLEEP_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (distanceToRun > 0);
listener.onRaceFinished(getClass().getSimpleName());
}
}
and a similar Tortoise class with these variables:
private static final int SLEEP_DURATION = 1000; //sleeps less
private static final int SPEED = 1; //but is slow
Then create a listener to get notified when someone has finished:
public interface RaceFinishListener {
void onRaceFinished(String finisher);
}
and finally your main class:
public class Test implements RaceFinishListener {
private String winner;
private static final int DISTANCE_TO_RUN = 10;
public static void main(String[] args) {
new Test().race();
}
private void race() {
Hare bob = new Hare(DISTANCE_TO_RUN, this);
Tortoise fred = new Tortoise(DISTANCE_TO_RUN, this);
new Thread(bob).start();
new Thread(fred).start();
}
#Override
public void onRaceFinished(String finisher) {
synchronized (this) {
if (winner == null) {
winner = finisher;
System.out.println(finisher + " is the winner!");
} else {
System.out.println(finisher + " lost.");
}
}
}
}
Output
Tortoise is the winner!
Hare lost.
After this line:
}while(bob.getTotalDistance() < winDistance && fred.getTotalDistance() < winDistance);
You would just have:
boolean bobWins = (bob.getTotalDistance() >= winDistance);
boolean fredWins = (fred.getTotalDistance() >= winDistance);
if (bobWins && fredWins) {
System.out.println("It's a tie");
}
else if (bobWins) {
System.out.println("Bob Wins");
}
else {
System.out.println("Fred Wins");
}
I want to use two threads to print Floyd triangle(say one thread prints the number and the other prints the number in the line) as below.
and so forth until the max number which is 15 in this case.
I tried following but it keeps on printing numbers one on each line
public class MyThread extends Thread{
static volatile int lineNumber = 1;
public static void main(String... args) {
PrintFloyd print = new PrintFloyd();
Thread t1 = new Thread(new TaskHandler(print, 10), "T1");
Thread t2 = new Thread(new TaskHandler(print, 10), "T2");
t1.start();
t2.start();
}
}
class TaskHandler implements Runnable {
static volatile int i = 1;
static volatile int lineCount = 1;
static volatile int lineNumber = 1;
private int max;
private PrintFloyd print;
TaskHandler(PrintFloyd print2, int max) {
this.print = print2;
this.max = max;
}
#Override
public void run() {
System.out.println(">>>>" + Thread.currentThread().getName());
while(i < max){
if (Thread.currentThread().getName().equals("T1")){
print.printNumber(i);
} else {
print.breakLine();
}
}
}
}
class PrintFloyd {
boolean isBreakPoint = false;
public void printNumber(int i) {
synchronized(this){
while (isBreakPoint == false) {
try {
wait();
} catch (InterruptedException ex) {
}
System.out.print(i++ + " ");
isBreakPoint = false;
notifyAll();
}
}
}
public void breakLine(){
synchronized(this){
while (isBreakPoint == true) {
try {
wait();
} catch (InterruptedException ex) {
}
}
System.out.println();
isBreakPoint = true;
notifyAll();
}
}
}
The following code would help:
public class PrintPatternWith2Threads {
final static int MAX = 15;
final static String itemWriterName = "itemWriter";
final static String newLineWriterName = "newLineWriter";
public static void main(String[] args) {
Printer print = new Printer(MAX);
Thread itemWriter = new Thread(new ItemWriter(print), itemWriterName);
itemWriter.start();
Thread newLineWriter = new Thread(new NewLineWriter(print), newLineWriterName);
newLineWriter.start();
}
}
class ItemWriter implements Runnable {
private Printer print;
ItemWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNumber();
}
}
}
class NewLineWriter implements Runnable {
private Printer print;
NewLineWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNewLine();
}
}
}
class Printer {
public final int MAX;
public int current = 1;
public int itemsInALine = 1;
Printer(int max) {
this.MAX = max;
}
public void printNumber() {
synchronized(this) {
for(int i = current; i < current + itemsInALine && i <= MAX; i++) {
System.out.print(i + " ");
}
this.current = current + itemsInALine;
itemsInALine++;
notifyAll();
try {
if(this.current < MAX) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printNewLine() {
synchronized(this) {
System.out.println();
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I am trying execute two jobs simultaneously. One of the things that I am trying to do is displaying a count up timer and the other one is moving the ball.
This is where I create the timer and also call the moveBall method
button.addChangeListener(new ChangeListener() {
int start = 0;
public void stateChanged(ChangeEvent e) {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
timeValue.setText(++start + " sec");
}
};
timer = new Timer(1000, taskPerformer);
timer.start();
ball.moveBall();
}
});
This is my moveBall method
public void moveBall() {
Thread ball = new Thread() {
double counter = 0;
int t = (int) (2 * Vy / 9.8);
public void run() {
try {
while (t >= 0) {
// calculate Vx and Vy
Ball.this.setX(Ball.this.getX() + Vx);
Ball.this.setY(Ball.this.getY() - Vy);
counter += 50;
if (counter == 1000) {
t--;
counter = 0;
}
paintingComponent.repaint();
Thread.sleep(20);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
ball.start();
}
When I execute the above code the label for displaying the time passed is not changing at all during the ball is moving and when the movement is over it takes the last number that it supposed to take.
This is a example two executions of two threads, Java simultaneous execution
public class ThreadExecutor extends Thread {
private String name;
private int executionCount;
public ThreadExecutor(final String name, final int executionCount) {
this.name = name;
this.executionCount = executionCount;
}
#Override
public void run() {
int count = 1;
while (count <= executionCount) {
System.out.println("Executing thread ".concat(name).concat(" : ") + count);
count++;
}
}
}
public class Main {
public static void main(String args[]) {
final ThreadExecutor one = new ThreadExecutor("One", 1);
final ThreadExecutor two = new ThreadExecutor("Two", 2);
one.start();
two.start();
}
}
I have two Timers in java that are scheduled independently. Both timers have different Task.
Timer 1 increments a number and Timer 2 changes the period of Timer 1. Here is the code where I am using two timers
public class Receiver
{
public static int totalBufferCapacity = 1024;
public static int totalPacketsDropped = 0;
public static int totalPacketsServiced = 0;
public static int totalPacketsReceived = 0;
public static int timesBufferGetsFull = 0;
public static int timesIntervelChanged = 0;
public static Socket clientSocket;
public static BufferedReader br;
public static ArrayList<String> buffer;
public static String START = "Start";
public static String STOP = "Stop";
public static String token = "1";
public static boolean flag;
public static Timer timer;
public static int Max = 80;
public static int Min = 40;
public static int rand;
public static PrintStream ps;
public static String packet;
public static Timer timer_2;
public static consumeArrayItems task;
public static void main(String[] args)
{
flag = true;
try
{
init(args[0], args[1]);
while (flag)
{
storePacketInArray();
}
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void init(String localHost, String portNumber)
{
try
{
// inet address which is local host in this case
InetAddress acceptorHost = InetAddress.getByName(localHost);
// port number at which the sender wants to communicate
int serverPortNum = Integer.parseInt(portNumber);
clientSocket = new Socket(acceptorHost, serverPortNum);
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void storePacketInArray()
{
try
{
if (br == null)
{
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
packet = new String(br.readLine());
if (packet.compareToIgnoreCase("Start") == 0)
{
token = START;
buffer = new ArrayList<String>(totalBufferCapacity);
} else if (packet.compareToIgnoreCase("Stop") == 0)
{
stopVaryingTimeSchedular();
stopSchedular();
} else
{
totalPacketsReceived += 1;
buffer.add(packet);
}
computeToken();
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void computeToken()
{
int bufferSize = buffer.size();
if (bufferSize > 0 && bufferSize < totalBufferCapacity)
{
float queueOccupancy = (bufferSize * 100 / totalBufferCapacity);
} else if (bufferSize == totalBufferCapacity)
{
token = "10";
timesBufferGetsFull += 1;
} else if (token.compareToIgnoreCase("Start") == 0)
{
token = START;
startSchedular();
startVaryingTimeSchedular();
} else
{
totalPacketsDropped += 1;
token = "15";
}
sendAcknowledgment();
}
public static void sendAcknowledgment()
{
try
{
if (ps == null)
{
ps = new PrintStream(clientSocket.getOutputStream());
}
String tokenAck = token;
if (packet.compareToIgnoreCase("Stop") != 0)
{
ps.println(tokenAck);
ps.flush();
}
if (!flag)
{
clientSocket.close();
}
} catch (IOException e)
{
e.printStackTrace();
}
}
public static void startSchedular()
{
rand = (int) (Math.random() * (Max - Min));
timer = new Timer();
task = new consumeArrayItems(true);
timer.scheduleAtFixedRate(task, 1, rand);
}
public static void stopSchedular()
{
timer.cancel();
timer.purge();
flag = false;
}
// After every 500 ms service time of packets will vary between Max and Min
public static void startVaryingTimeSchedular()
{
timer_2 = new Timer();
timer_2.scheduleAtFixedRate(new varyServiceTime(), 0, 500);
}
public static void stopVaryingTimeSchedular()
{
timer_2.cancel();
timer_2.purge();
}
}
class consumeArrayItems extends TimerTask
{
public synchronized void run()
{
if (Receiver.buffer.size() > 0)
{
Receiver.totalPacketsServiced += 1;
Receiver.buffer.remove(Receiver.buffer.size() - 1);
}
}
}
class varyServiceTime extends TimerTask
{
public synchronized void run()
{
Receiver.timer.cancel();
Receiver.timer = null;
Receiver.rand = (int) (Math.random() * (Receiver.Max - Receiver.Min));
Receiver.timer = new Timer();
Receiver.timer.scheduleAtFixedRate(new consumeArrayItems(), 0,Receiver.rand);
Receiver.timesIntervelChanged += 1;
}
}
Timer 2 never gets scheduled. What wrong I am doing here.