Multi Threading - Request input once for all variables (Java) - java

Below are codes and outputs for a multithreading function whereby there is a counter and functions of add, subtract, multiply and divide. I'm using Eclipse.
4 Threads for each mathematical function:
public class Maths {
public static void main(String args[]){
CalculationThread T1 = new CalculationThread("Addition");
T1.start();
CalculationThread T2 = new CalculationThread("Subtraction");
T2.start();
CalculationThread T3 = new CalculationThread("Multiplication");
T3.start();
CalculationThread T4 = new CalculationThread("Division");
T4.start();
}
}
class CalculationThread extends Thread{
private Thread t;
private String maths;
private int count = 0;
private int resultplus, resultminus, resulttimes, resultdivide = 0;
CalculationThread(String answer){
maths = answer;
}
public void start(){
System.out.println("Starting calculation of " + maths + "\n");
if(t == null){
t = new Thread (this, maths);
t.start();
}
}
Here is where the functions take place, it will use the counters as 2 numbers to perform an equation.
public void run(){
try {
for (int x=0; x<=3 ; x++){
if(maths == "Addition"){
System.out.println("Calculating: " + maths + " of " + count +
" + "+ count + " = " + resultplus + "\n");
Thread.sleep(3000);
count++;
resultplus = count + count;
}
else if(maths == "Subtraction"){
System.out.println("Calculating: " + maths + " of " + count +
" - "+ count + " = " + resultminus + "\n");
Thread.sleep(3000);
count++;
resultminus = count - count;
}
else if(maths == "Multiplication"){
System.out.println("Calculating: " + maths + " of " + count +
" * "+ count + " = " + resulttimes + "\n");
Thread.sleep(3000);
count++;
resulttimes = count * count;
}
else if(maths == "Division"){
System.out.println("Calculating: " + maths + " of " + count +
" / "+ count + " = " + resultdivide + "\n");
Thread.sleep(3000);
count++;
resultdivide = count / count;
}
}
}
catch (InterruptedException e){
System.out.println("Math function failed");
}
if(maths == "Addition"){
System.out.println("Addition completed.");
}
else if(maths == "Subtraction"){
System.out.println("Subtraction completed.");
}
else if(maths == "Multiplication"){
System.out.println("Multiplication completed.");
}
else if(maths == "Division"){
System.out.println("Division completed.");
}
}
}
The output:
Starting calculation of Addition
Starting calculation of Subtraction
Calculating: Addition of 0 + 0 = 0
Starting calculation of Multiplication
Calculating: Subtraction of 0 - 0 = 0
Starting calculation of Division
Calculating: Multiplication of 0 * 0 = 0
Calculating: Division of 0 / 0 = 0
Calculating: Subtraction of 1 - 1 = 0
Calculating: Addition of 1 + 1 = 2
Calculating: Multiplication of 1 * 1 = 1
Calculating: Division of 1 / 1 = 1
Calculating: Addition of 2 + 2 = 4
Calculating: Subtraction of 2 - 2 = 0
Calculating: Division of 2 / 2 = 1
Calculating: Multiplication of 2 * 2 = 4
Calculating: Subtraction of 3 - 3 = 0
Calculating: Addition of 3 + 3 = 6
Calculating: Division of 3 / 3 = 1
Calculating: Multiplication of 3 * 3 = 9
Subtraction completed.
Addition completed.
Division completed.
Multiplication completed.
The code above works whereby all 4 functions will be done simultaneously , but whenever I try including a JOptionPane for user input instead of an automatic counter, each of the 4 threads will request at a time. Thus its not counted as multithreading if the functions are waiting for me to input 2 numbers. How and in what way can I include a user input that only requires user to input at the beginning so that all functions can use the 2 variables.

I'm not sure if I understood it correctly.
If you just want to block the calculation threads and wait for an initial user Input you can use a Semaphore.
The UI Thread that waits for the user input shows the dialog and releases the waiting calculation threads by setting the number of permits / threads.
Here is an example how this could look like (it also uses an more object oriented approach). For simplicity, I've skipped the Multiplication and Division Tasks
import java.util.concurrent.Semaphore;
import javax.swing.JOptionPane;
public class MathSample {
// because updated / read from different threads mark as volatile
private volatile int a, b;
// semaphore with no initial permits i.e.
// the calculations will wait until permits are available.
private Semaphore available = new Semaphore(0);
private abstract class Task implements Runnable {
public abstract void doCalculation();
public abstract String getName();
#Override
public void run() {
try {
// wait until a permit becomes available
available.acquire();
// not sure what should happen here
// wait again for user input?
for (int x = 0; x < 50; ++x) {
a = a + x;
doCalculation();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(String.format("Task %s completed.", getName()));
}
}
private class AdditionTask extends Task {
public void doCalculation() {
System.out.println(String.format("Calculating: Addition of + %d + %d = %d", a, b, a+b));
}
public String getName() {
return "Addition";
}
}
private class SubstractionTask extends Task {
public void doCalculation() {
System.out.println(String.format("Calculating: Substraction of + %d - %d = %d", a, b, a-b));
}
public String getName() {
return "Substraction";
}
}
private void run() {
new Thread(new AdditionTask()).start();
new Thread(new SubstractionTask()).start();
a = Integer.parseInt(JOptionPane.showInputDialog("First value"));
b = Integer.parseInt(JOptionPane.showInputDialog("Second value"));
available.release(2); // let the 2 calculation threads run
}
public static void main(String ...args) {
new MathSample().run();
}
}
As you can see you don't have to overwrite the start method of the Thread to run a different thread.
Your start method of your CalculationThread is at least strange because you overwrite the start method of the Thread class and within that you create another Thread instance where you pass your CalculationThread as Runnable.
Easier / better:
class Calculation implements Runnable {
...
#override
public void run() {
// the name you passed to the thread is your math
// lets get it from the currently running thread where it is stored.
final String math = Thread.currentThread().getName();
...
}
}
// somewhere else
new Thread(new CalculationThread, math).start();

You can refer following codes.
Maybe it will suit your needs according to my understanding on your question. I also applied .equals() to the code according to Hovercraft Full Of Eels suggestion.
import javax.swing.JOptionPane;
public class Maths {
public static void main(String[] args) {
// TODO Auto-generated method stub
String num1 = JOptionPane.showInputDialog("Num1: ");
String num2 = JOptionPane.showInputDialog("Num2: ");
int num11 = Integer.parseInt(num1);
int num22 = Integer.parseInt(num2);
calculationThread T1 = new calculationThread("Addition");
T1.getNumber(num11, num22);
T1.start();
calculationThread T2 = new calculationThread("Subtraction");
T2.getNumber(num11, num22);
T2.start();
calculationThread T3 = new calculationThread("Multiplication");
T3.getNumber(num11, num22);
T3.start();
calculationThread T4 = new calculationThread("Division");
T4.getNumber(num11, num22);
T4.start();
}
}
class calculationThread extends Thread{
private Thread t;
private String maths;
private int a;
private int b;
private int resultplus = 0;
private int resultminus = 0;
private int resulttimes = 0;
private int resultdivide = 0;
public void getNumber(int num1, int num2){
a = num1;
b = num2;
}
calculationThread(String answer){
maths = answer;
}
public void start(){
System.out.println("Starting calculation of " + maths + "\n");
if(t == null){
t = new Thread(this, maths);
t.start();
}
}
public void run(){
try {
for (int x=0; x<=3 ; x++){
if(maths.equals("Addition")){
System.out.println("Calculating: " + maths + " of " + a +
" + "+ b + " = " + resultplus + "\n");
Thread.sleep(3000);
resultplus = a + b;
}
else if(maths.equals("Subtraction")){
System.out.println("Calculating: " + maths + " of " + a +
" - "+ b + " = " + resultminus + "\n");
Thread.sleep(3000);
resultminus = a - b;
}
else if(maths.equals("Multiplication")){
System.out.println("Calculating: " + maths + " of " + a +
" * "+ b + " = " + resulttimes + "\n");
Thread.sleep(3000);
resulttimes = a * b;
}
else if(maths.equals("Division")){
System.out.println("Calculating: " + maths + " of " + a +
" / "+ b + " = " + resultdivide + "\n");
Thread.sleep(3000);
resultdivide = a / b;
}
}
}
catch (InterruptedException e){
System.out.println("Math function failed");
}
finally{
if(maths.equals("Addition")){
System.out.println("Addition completed.");
}
else if(maths.equals("Subtraction")){
System.out.println("Subtraction completed.");
}
else if(maths.equals("Multiplication")){
System.out.println("Multiplication completed.");
}
else if(maths.equals("Division")){
System.out.println("Division completed.");
}
}
}
}

Related

Ticket System + Timer

I'm currently working on an offline Jackpot system for fun, and i got stuck with the ticket problem.
Basically I want it to be (which seems to me like the best way to do it) so for every 10$ a user enters, you'll get 1 ticket. so let's say Jason deposits 250$, then he gets tickets 1-25, Bob deposits 100$ then he gets tickets 26-36. etc etc
then in the end it'd pick a random number and it'd pick a player that has that number in his range.
this is the current code:
public class Main {
private static int totalPlayers = 0;
private static int totalMoney = 0;
private static int playerDeposit = 0;
private static ArrayList<String> players = new ArrayList<String>();
private static ArrayList<Integer> botsMoney = new ArrayList<Integer>();
private static Timer timer;
private static Random random = new Random();
private static int playerMoney = 500;
private static String playerName;
private static double playerChance;
public static void main(String[] args) {
onUserEnter();
}
public static boolean onUserEnter(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter your name:");
playerName = scan.nextLine();
System.out.println("Money: 500$");
System.out.println("How much would you like to deposit?");
try{
playerDeposit = scan.nextInt();
}catch(NumberFormatException ex) {
System.out.println(playerDeposit + " is not a proper number!");
playerDeposit = 0;
return false;
}
if(playerDeposit <= 0) {
System.out.println("You can't deposit " + playerDeposit + "$");
return false;
}else if(playerDeposit > playerMoney){
System.out.println("You can't deposit more money than what you have!");
return false;
}
playerMoney -= playerDeposit;
System.out.println("You now have: " + playerMoney + "$");
players.add(playerName);
totalPlayers = players.size();
totalMoney += playerDeposit;
System.out.println(totalPlayers + " Players: " + players);
System.out.println("Total Pot: " + totalMoney + ", Your chances: 100%");
TimerTask tasknew = new TimerTask() {
#Override
public void run() {
}
};
timer = new Timer();
timer.schedule(tasknew, 20000);
botJoin();
return true;
}
public static boolean botJoin(){
botsMoney.add(5355);
int x = 0;
while(true){
int willBotJoin = random.nextInt(1000000000);
if(willBotJoin <= 2){
if(players.size() >= 10) {
break;
}
int moneyBotDeposits = random.nextInt(1100);
botsMoney.add(moneyBotDeposits);
double tickets = (double) moneyBotDeposits / 10;
x++;
players.add("Bob #" + x);
totalPlayers = players.size();
totalMoney += moneyBotDeposits;
System.out.println(totalPlayers + " Players: " + players);
playerChance = ((double) playerDeposit / totalMoney) * 100;
System.out.println("Total Pot: " + totalMoney + "$, Your chances: " + playerChance + "%");
}
}
botsPrecentage();
return true;
}
public static boolean botsPrecentage(){
for (int i = 1; i <= 9; i++){
double botPrecent = ((double) botsMoney.get(i) / totalMoney) * 100;
String botName = players.get(i);
System.out.println(botName + " has " + botPrecent + "%");
}
System.out.println(playerName + " has " + playerChance + "%");
return true;
}
Also I tried setting up a timer which I don't understand how, I've looked up Timer online but I just can't understand the explanations.

Binomial in Java saving 2 variables in a variable after getting user input

I try to save both user input after the iteration, but I'm not sure how to do it. I always get
java:19: error: variable x might not have been initialized
long resalt = bio(x, y);
Source code:
import java.util.Scanner;
public class Aufgabe11 {
public static void main (String [] args) {
Scanner pit = new Scanner(System.in);
System.out.println("Enter fac number");
long a = pit.nextLong();
long result = recFac(a);
System.out.println("The factorial of" + " "+ a + " " + "is"+ " " + result);
Scanner pat = new Scanner(System.in);
long[] vars = new long [2];
for(int i = 0; i < vars.length; i++){
System.out.println("Enter bio var:");
vars [i] = pat.nextLong();
}
long x,y = pat.nextLong();
long resalt = bio(x, y);
System.out.println("The bio of" + " " + x + "over" + y + "is" + " " + resalt);
}
public static long recFac (long a) {
if (a <= 1) {
return 1;
}
else {
return a * recFac (a-1);
}
}
public static long bio (long x, long y) {
if ((x == y) || (y == 0))
return 1;
else
return bio (x-1, y) + bio (x-1, y-1);
}
}

Getting average from a random duration

I'm trying to print the maximum, minimum and average of the duration at the end of this code but i'm not too sure how to store the random duration in a specific array to display it after at the end. Below is the code:
public void test(){
int max;
int average;
int min;
long duration=2;
try
{ System.out.println("Bus Needs Cleaning" + "\n");
Thread.sleep(1000);
System.out.println("Bus getting cleaned");
Thread.sleep(1000);
duration = (long)(Math.random()*20);
TimeUnit.SECONDS.sleep(duration);
}
catch(InterruptedException iex)
{
}
System.out.println("Cleaner completed cleaning in" + duration + "Seconds");
System.out.println("Bus Leaves");
System.out.println("Average Waiting Time: " + average + " | Maximum: "+ max + " | Minimum" + min +"\n");
}
Any help would be much appreciated thanks!
EDIT: There are 5 buses coming in and going out and displaying different durations and they all go through the cleaning phase
please try this one. as far as I understood
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class BusRandom {
public static void main(String[] args) {
new BusRandom().test();
}
public void test() {
long max = 0;
double average = 0;
long min = Long.MAX_VALUE;
int totalBuses=5;//change accordinly
List<Long> randomList = new ArrayList<>();
long duration = 2;
try {
for (int i = 0; i <totalBuses; i++) {
System.out.println("Bus Needs Cleaning" + "\n");
Thread.sleep(1000);
System.out.println("Bus getting cleaned");
Thread.sleep(1000);
duration = (long) (Math.random() * 20);
randomList.add(duration);
TimeUnit.SECONDS.sleep(duration);
System.out.println("Cleaner completed cleaning in" + duration + "Seconds");
System.out.println("Bus Leaves");
max=max>duration?max:duration;
min=min<duration?min:duration;
}
} catch (InterruptedException iex) {
}
double sum=0;
for(long l:randomList){
sum+=l;
}
average=(double) (sum/randomList.size());
System.out.println("Average Waiting Time: " + average + " | Maximum: " + max + " | Minimum" + min + "\n");
}
}

Java Swing Timer getting faster and faster

I'm working on a small turn based RPG. For every turn, one of the two characters tries to hit the other character then 2000ms later, the timer restarts the attack method (to give time to the player to read the outcome of each turn). After the battle, the player goes back to the level map where he can choose to move away or initiate another battle. Here's my problem: Every time the player initiates a new battle, the Timer delay is shorter and shorter so the battle happens too fast at some point. First fight, each turn will be 2 seconds, then 1 second, then 500ms, and so on. Here's my code, what am I missing?
public void attack(Character a, Character d) {
//Calculations//////////////////////////////////////////////
///////////////////unit a (attacker)////////////////////////
Weapon aWep = (Weapon) a.inventory[0];
double aCritRate = (double) (a.skl / 2 + aWep.crit - d.lck) / 100;
double aHitRate = (double) (aWep.acc + (a.skl * 2) + (a.lck / 2)) / 100;
double aAvoidRate = (double) (a.spd * 2 + a.lck) / 100;
int aAttackPower = (a.pow + aWep.dmg);
boolean aTwice = a.spd >= d.spd + 4 ? true : false;
///////////////////unit d (defender)////////////////////////
Weapon dWep = (Weapon) d.inventory[0];
double dCritRate = (double) (d.skl / 2 + dWep.crit - a.lck) / 100;
double dHitRate = (double) (dWep.acc + (d.skl * 2) + (d.lck / 2)) / 100;
double dAvoidRate = (double) (d.spd * 2 + d.lck) / 100;
int dAttackPower = (d.pow + dWep.dmg);
boolean dTwice = d.spd >= a.spd + 4 ? true : false;
int delay = 2000;
Timer timer;
ActionListener repeat = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
switch(bturn){
case(1):attack(d,a); break;
default:break;
}
}
};
timer = new Timer(delay,repeat);
//Battle/////////////////////////
int aDmg = aAttackPower - d.def;
double aHitChance = aHitRate - dAvoidRate;
String sound;
//Turn 1
if (aHitChance >= rngs[rngsIndex]) {
if (aCritRate >= rngs[rngsIndex]) {
aDmg *= 3;
sound="crit.wav";
t.print("Critical Hit! " + a.name + " attacks " + d.name + " for " + aDmg + " damage!");
rngsIndex++;
} else {
sound="hit.wav";
t.print(a.name + " attacks " + d.name + " for " + aDmg + " damage!");
rngsIndex++;
}
d.damageHp(aDmg);
rngsIndex++;
} else {
sound = "miss.wav";
t.print(a.name + " has missed.");
rngsIndex++;
}
playSound(sound);
if (d.isDead) {
String add = t.text.getText();
add+=" " + d.name + " has been killed.";
t.print(add);
a.xp+=35;
charPane.set(a);
grid[d.x][d.y].removeMouseListener(grid[d.x][d.y].hover);
killUnit(d, grid[d.x][d.y]);
}
if (d.faction.equals("e")) {
enemPane.set(d);
} else {
charPane.set(d);
}
//Turn 2
bturn++;
if(!d.isDead && bturn==1){
System.out.println("REACHED");
timer.start();
}
else{
timer.stop();
bturn = 0;
grid[d.x][d.y].removeActionListener(grid[d.x][d.y].targetable);
clearGrid();
loop();
}
}
Try to log which instance of ActionListener repeat caused the attack. I think you will see, that the speedup is caused by having more instances of Timer and ActionListener then you want.
After each run, number of those instances doubles, hence the exponencial growth of number of turns per second.
In absence of logger:
public void actionPerformed(ActionEvent e)
{
System.out.println("" + LocalDateTime.now() + " " + this);
switch(bturn){

Problems with while() loop [duplicate]

This question already has answers here:
Comparing two integer arrays in Java
(10 answers)
Closed 7 years ago.
The statement before the begining of while loop System.out.println("Value of i before loop = " + i); is not being printed and the value of i in the loop is not being printed starting from 1. Instead it starts printing from a random big int.
package main;
import java.util.Random;
public class Main {
public static void main(String args[]){
Random ran = new Random();
int[] in = {2,5,9};
int[] c_gen = new int[3];
int i = 0;
System.out.println("Value of i before loop = " + i);
while(!(c_gen.equals(in))){
c_gen[0] = ran.nextInt(10);
c_gen[1] = ran.nextInt(10);
c_gen[2] = ran.nextInt(10);
i++;
System.out.println(c_gen[0] + " " + c_gen[1] + " " + c_gen[2] + " .................." + i);
}
System.out.print("in = ");
for(int x : in)
System.out.print(x + " ");
System.out.print("\n" + "c_gen = ");
for(int x : c_gen)
System.out.print(x + " ");
System.out.println("\n" + "i = " + i);
}
}
You are directly comparing arrays resulting in an infinite loop. Those results are being printed but are going to be at the top of tons and tons of output. Fix your comparison.
Sotirios' intuition is correct - your bug is in the line while(!(c_gen.equals(in))). You can't compare arrays for equality using the .equals(...) method because "arrays inherit their equals-method from Object, [thus] an identity comparison will be performed for the inner arrays, which will fail, since a and b do not refer to the same arrays." (source). Thus because c_gen and in will always refer to different arrays (even if their contents are the same), your loop will go forever.
Try Arrays.equals(..) instead:
public static void main(String[] args) {
Random ran = new Random();
int[] in = {2,5,9};
int[] c_gen = new int[3];
int i = 0;
System.out.println("Value of i before loop = " + i);
while(!Arrays.equals(in, c_gen)){
c_gen[0] = ran.nextInt(10);
c_gen[1] = ran.nextInt(10);
c_gen[2] = ran.nextInt(10);
i++;
System.out.println(c_gen[0] + " " + c_gen[1] + " " + c_gen[2] + " .................." + i);
}
System.out.print("in = ");
for(int x : in)
System.out.print(x + " ");
System.out.print("\n" + "c_gen = ");
for(int x : c_gen)
System.out.print(x + " ");
System.out.println("\n" + "i = " + i);
}
This works (terminates in finite time) for me, with sample output:
Value of i before loop = 0
1 9 9 ..................1
5 4 1 ..................2
1 1 6 ..................3
1 3 6 ..................4
.... //Omitted because of space
6 5 8 ..................1028
2 5 9 ..................1029
in = 2 5 9
c_gen = 2 5 9
i = 1029
I get:
Value of i before loop = 0
2 2 1 ..................1
2 2 4 ..................2
...
Suggest you rebuild the project and try again.
As originally posted your code will not terminate because int[].equals(int[]) will not do what you expect.
You could try this though.
private static boolean equals(int[] a, int[] b) {
if (a == null && b == null) {
// Both null
return true;
}
if (a == null || b == null) {
// One null
return false;
}
if (a.length != b.length) {
// Differ in length.
return false;
}
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
// Mismatch
return false;
}
}
// Same.
return true;
}
public void test() {
Random ran = new Random();
int[] in = {2, 5, 9};
int[] c_gen = new int[3];
int i = 0;
System.out.println("Value of i before loop = " + i);
while (!equals(c_gen, in)) {
c_gen[0] = ran.nextInt(10);
c_gen[1] = ran.nextInt(10);
c_gen[2] = ran.nextInt(10);
i++;
System.out.println(c_gen[0] + " " + c_gen[1] + " " + c_gen[2] + " .................." + i);
}
System.out.print("in = ");
for (int x : in) {
System.out.print(x + " ");
}
System.out.print("\n" + "c_gen = ");
for (int x : c_gen) {
System.out.print(x + " ");
}
System.out.println("\n" + "i = " + i);
}

Categories