Java access Thread's class attributes - java

I'm building a console game in Java that works like this: It prints you an operation (e.g: 3 x 4) and you must write the result (12 in this case), and it will give you operations during a period of 1 minute and then it will finish.
I knew from the beginning I had to use threads to catch the user input, so this is the thread's logic:
public class UserInput extends Thread {
private int answer;
#Override
public void run() {
Scanner in = new Scanner(System.in);
while(true){
answer = in.nextInt();
}
}
public int getAnswer(){
return answer;
}
}
quite simple, now the game's logic:
public static void play() {
Game game = new EasyGame();
UserInput ui = new UserInput();
long beginTime = System.currentTimeMillis()/1000;
ui.start();
boolean accepted = true;
while(timeLeft(beginTime)){
//PrintChallenge() prints an operation and store its result in game
if(accepted) game.PrintChallenge();
accepted = false;
if(ui.getAnswer() == game.getResult()) accepted = true;
}
}
//returns if current time is 60 seconds after initial time
public static boolean timeLeft(long time){
return (System.currentTimeMillis()/1000) < (time + 60);
}
but it isn't working, it simply never matches ui's getAnswer() with game's getResult(). What am I doing wrong on this thread and game logics?

I think your problem is Java caching the value of your int locally, though it could be due to something in your game.getResult(), since I cannot check this. Thread safety is difficult in java.
To confirm:
I built a dumb version of the game, without any game logic or timer.
I added a volatile keyoword to your answer int, this makes Java check main memory rather than local cache for the value of the int.
The following code outputs once the user enters "30", removing the "volatile" keyoword in user input leads to your situation.
See below:
package stackOverflowTests;
import java.util.Scanner;
public class simpleGame {
public static class UserInput extends Thread {
volatile private int answer;
public void run() {
Scanner in = new Scanner(System.in);
while(true){
System.out.print("Answer meeee!:");
answer = in.nextInt();
}
}
public int getAnswer(){
return answer;
}
}
public static void play() throws InterruptedException {
UserInput testInput = new UserInput();
testInput.start();
while(true){
//PrintChallenge() prints an operation and store its result on game
Thread.sleep(10);
if(testInput.getAnswer()==30)System.out.println(testInput.getAnswer()+ " : "+(testInput.getAnswer()==10));
}
}
public static void main(String[] args) throws InterruptedException{
play();
}
}

private int answer;
This variable needs to be volatile, as you are reading and writing it from different threads. Or else you need to synchronize all access to it, both reads and writes.

Related

Where should I put the while loop/boolean?

I made a method should pull up a menu with a list of actions, allows users to choose an action, execute the action, then goes back to the menu and repeats until the user chooses to end the session. I'm currently at a bit lost on what to do with the while loop and the boolean endSession(), which I've been shuffling around in the code that sometimes lets me compile it and never does what I want it to do. The place I currently have it causes it to not only skip the action, but loop infinitely. I don't really need to know what's exactly wrong, I just want to know where to put the while loop/boolean endSession (and although not necessary, an explaination for why the answer works would be nice).
//package bookStoreLab;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
public class BookStoreDriver {
private static final int PRINT_INVENTORY=1;
private static final int SEARCH_TITLE=2;
private static final int SEARCH_AUTHOR=3;
private static final int AVAILABLE_BOOKS=4;
private static final int NEW_RELEASES=5;
private static final int PURCHASE=6;
private static final int ADD_INVENTORY=7;
//include rest of constants here for all choices
private static Scanner keyboard;
public static void main(String[] arg) throws IOException, FileNotFoundException{
System.out.println("\f");
keyboard = new Scanner(System.in);
BookStore booky = new BookStore();
System.out.println("*****" +
"Welcome To Your Local Book Store!" + "*****");
booky.inputBooks();
boolean endSession = false;
int choice = getChoice(endSession);
if(choice==0){
endSession = true;
}
if(choice==PRINT_INVENTORY){
booky.printInventory();
}
if(choice==SEARCH_TITLE){
booky.searchByTitle();
}
if(choice==SEARCH_AUTHOR){
booky.searchByAuthor();
}
if(choice==AVAILABLE_BOOKS){
booky.printAvailableBooks();
}
if(choice==NEW_RELEASES){
booky.printNewReleases();
}
if(choice==PURCHASE){
booky.purchase();
}
if(choice==ADD_INVENTORY){
booky.addToInventory();
}
else{
System.out.println("Please choose an option that's actually listed.");
}
printFarewell();
}
public static int getChoice(boolean a){
int choice=-1;
while(!a){
System.out.println("\n\nWhat store service would you like" +
"to perform? (Enter 0-7)");
System.out.println("\t0. Enter 0 to end your session");
System.out.println("\t1. View all books");
System.out.println("\t2. Search by title");
System.out.println("\t3. Search by author");
System.out.println("\t4. View available books for purchase");
System.out.println("\t5. View new releases");
System.out.println("\t6. Purchase one or more copies of a book");
System.out.println("\t7. Add book(s) to inventory");
System.out.println("Enter your choice: ");
choice = keyboard.nextInt();
}
return choice;
}
public static void printFarewell(){
System.out.println("\n\nThank you for using the system!");
}
}
So far I've tried:
-getting rid of parameter a for getChoice() and moving the while loop to before if(choice==0) and ended it at the else statement
while(!endSession){
if(choice==0){
endSession = true;
}
if(choice==PRINT_INVENTORY){
booky.printInventory();
}
if(choice==SEARCH_TITLE){
booky.searchByTitle();
}
if(choice==SEARCH_AUTHOR){
booky.searchByAuthor();
}
if(choice==AVAILABLE_BOOKS){
booky.printAvailableBooks();
}
if(choice==NEW_RELEASES){
booky.printNewReleases();
}
if(choice==PURCHASE){
booky.purchase();
}
if(choice==ADD_INVENTORY){
booky.addToInventory();
}
else{
System.out.println("Please choose an option that's actually listed.");
}
}
which resulted in the action looping infinitely (for example: repeatly doing printInventory() until I forced the console to stop).
-moving the boolean endSession to inside getChoice() (no parameters), which almost works, except for the part where it skips doing the action (for example: entering 1, and the menu immediately popping back up without doing printInventory()).
Put the while loop in the main method. Your boolean value never changes inside your method, so your while loop will either run 0 times or infinite times.
Let your helper method collect a single input, and let the loop in your main method inspect the last returned value and determine whether to execute another iteration of the loop.
public static void main(String[] args) {
int choice = getChoice();
while(choice != 0) {
choice = getChoice();
}
}
public static int getChoice() {
// display menu
// collect user input
// return user input
}
1) get rid of the parameters,
2) put the while loop before int choice = getChoice(),
3) end it after the else loop.
I have no idea why that works but I'm too tired to care so yeet!

how can I get array values back from a thread

I have a thread, in Java, putting the first 100 Fibonacci numbers in an array. How do I get the numbers back from the thread. Is there an interrupt, handling, exception, implements, extends? I have been adding things and the trial and error is not getting me anywhere to understanding.
import java.util.Scanner;
import java.io.*;
import java.lang.Thread; //don't know if this is needed
public class FibThread extends Thread{
public FibThread (){
super();
}
public void run(int inputNum){
System.out.println(inputNum);
long[] fibArray = new long[inputNum];
fibArray[0]=0;
fibArray[1]=1;
fibArray[2]=1;
for(int i = 3; i<inputNum; i++){
fibArray[i]= fibArray[i-1] + fibArray[i-2];
// }
//System.out.println( );
// for(int j = 0; j<= inputNum; j++){
int output = (int) fibArray[i];
System.out.println(output);
}
}
public static void main(String[] args){
Scanner keyboard = new Scanner(System.in);
FibThread threadOne;
int inputNum, itter, output;
System.out.println("Please enter the number of Fibonacci numbers to be generated: ");
itter = keyboard.nextInt();
//inputNum = itter;
threadOne = new FibThread();
threadOne.start();
// for(int j = 0; j<= inputNum; j++){
// int output = (int) fibArray[j];
// System.out.println(output);
}
}
If you have a "task" that returns a value, make it a Callable.
If you want the callable to run in a background thread, then instead of handling the creation and execution of threads yourself, it's generally better to abstract this through an ExecutorService. A caller can interact with the service by passing in a Callable, and getting back a Future that will be populated with the value when the calculation has completed.
To modify your example, renaming FibThread to FibCalc:
public class FibCalc implements Callable<Integer> {
// We need some way to pass in the initial input - must be through the
// constructor and we'll store it here
private final inputNum;
public FibCalc(int inputNum) {
this.inputNum = inputNum;
}
public int call() {
// The same as your run() method from before, except at the end:
...
return output;
}
}
// And now for your main() method
public static void main(String[] args) throws Exception {
// As before up to:
...
itter = keyboard.nextInt();
// Create a very simple executor that just runs everything in a single separate thread
ExecutorService exec = Executors.newSingleThreadExecutor();
// Create the calculation to be run (passing the input through the constructor)
FibCalc calc = new FibCalc(itter);
// Send this to the executor service, which will start running it in a background thread
// while giving us back the Future that will hold the result
Future<Integer> fibResult = exec.submit(fibCalc);
// Get the result - this will block until it's available
int result = fibResult.get();
// Now we can do whatever we want with the result
System.out.println("We got: " + result);
}
If you absolutely have to create a Thread object yourself (due to artificial constraints on a homework question, or something like that - I can't see why one would realistically do this in reality), then the approach has to be different. You can't return a value because run() must return void due to the interface. So my approach here would be to store the result in a local variable of the FibThread class, and then add a method to that class (e.g. public int getResult()) which returned that variable.
(If you're doing it this way, bear in mind that you'll have to handle the concurrency issues (i.e. letting the caller know the result is ready) yourself. A naive approach, where the main method starts the thread and then immediately calls getResult(), means that it will almost certainly get an "empty" result before the calculation has finished. A crude solution to this problem would be calling join() on the spawned thread, to wait for it to finish before accessing the result.)

Creating three threads in Java to compute three different items

I'm trying to write my solution to a problem of multithreading in Java:
Create three separate threads that will calculate the average, minimum
and maximum of a series of numbers that is passed to the program. The
values will be stored globally in the program. The three threads will
return the three values respectively to the main program where it will
be output to the user.
I'm new to Java, so I've got one basic question about the approach to this program: How do I create three separate threads that will perform three different functions? While reading multithreading, I've come across several examples wherein three(or more) threads were created which would each execute a single function: counting down a loop. Thus requires only a single call to public void run() and one can very easily create three instances of a class that implements Runnable to do this, something like:
// Create multiple threads.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
class MultiThreadDemo {
public static void main(String args[]) {
new NewThread("One"); // start threads
new NewThread("Two");
new NewThread("Three");
try {
// wait for other threads to end
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
I am not sure how to create threads that perform separate functions: calculate double, min and max. So far, I've created one thread that calculates the average and returns it to the main program. This is my code [till now]:
package assignment2;
class Q2Thread implements Runnable {
String name;
Thread t;
private int average;
int sum=0;
Q2Thread(String name)
{
this.name=name;
t=new Thread(this, name);
//System.out.println("This thr");
t.start();
}
public void run()
{
try
{
for(int i=0;i<Q7Main.arr.length;i++)
sum+=Q7Main.arr[i];
average=sum/Q7Main.arr.length;
}
//catch(InterruptedException e)
finally
{
System.out.println("Calcuated average.");
}
System.out.println("Child Thread exiting.");
}
public int getAverage()
{
return average;
}
}
package assignment2;
import java.util.*;
public class Q7Main {
public static int[] arr=new int[5];
static Scanner in=new Scanner(System.in);
private static int finalAverage;
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Please enter the numbers: " );
for(int i=0;i<arr.length; i++)
arr[i]=in.nextInt();
System.out.println("You entered the numbers: ");
for(int x: arr)
{
System.out.print(x+ " ");
}
System.out.println();
Q2Thread obj=new Q2Thread("Average");
try
{
obj.t.join();
}
catch(InterruptedException e)
{
System.out.println("Interrupted.");
}
finalAverage=obj.getAverage();
System.out.println("The average of the numbers is: "+ finalAverage);
}
}
I have two questions now:
Can someone give me the approach to creating two more threads that will compute the min and max?
Are there any OOP defects in my code(thus far) that I should be aware of?
What you can do is create two other classes that calculate min and max, create an object of each of them obj1 and obj2. Since the constructor starts the thread for you, you should now have 3 threads running asynchronously.
Call obj1.t.join() and obj2.t.join() within that try block. So it should look like this:
try{
obj.t.join();
obj1.t.join();
obj2.t.join();
}
catch(InterruptedException e)
{
System.out.println("Interrupted.");
}
int average = obj.getAverage();
int max = obj1.getMax();
int min = obj2.getMin();
And then do whatever you want with these numbers.
As for some general comments, firstly I would not have a thread object as an attribute within the runnable class, nor have the start() method within the constructor. Instead, within the main class, I would encourage you to create three thread objects with an instance of each runnable class, and then invoke the start() method on each of them. Furthermore, instead of the three runnable
classes all interacting with the same static array found in Q7Main, I would instead update their
constructors to accept the array as a parameter in the constructor, and then have each of them interact with a unique array object when their run method is invoked. Otherwise, you have an issue that when one thread changes the value of something in the array, you get unexpected results.
Of course in this case none of your classes do that, but its something to keep in mind.
For example
Q2Thread obj =new Q2Thread("Average", arr);
Q2MaxThread obj1 = new Q2MaxThread("Maximum", arr);
Q2MinThread obj2 = new Q2MinThread("Minimum", arr);
Thread avThread = new Thread(obj);
Thread maxThread = new Thread(obj1);
Thread minThread= new Thread(obj2);
avThread.start();
maxThread.start();
minThread.start();
try{
avThread.join();
maxThread.join();
minThread.join();
}
catch(InterruptedException e)
{
System.out.println("Interrupted.");
}
int average = obj.getAverage();
int max = obj1.getMax();
int min = obj2.getMin();
Further to the #ElvenAshwin answer you should probably take three classes as private inner class.... good practice as you build bigger things you dont pollute public api. As an alternate and good exercise, think about doing it with lambdas in java 8. Its just a function you need not the class.

Java How to programm Deitel Book exercise 6.35

I've been studying Deitel's Book(Java how to program) and I want to solve exercise 6.35. Here's what it asks:
Write a program to assist a student to learn multiplication.Use a Random object to produce two positive integers (one digit each).
The program should show on screen something like this:("How much is 7 times 3")
Then the student should insert the answer and the program controls if the answer is correct or wrong.If it's correct the program continue asking another question,else the program waits until the student answer is correct.For every new question it must be a new method created(this method should be called once when the application starts and when the user answers correct to a question).
How do I do this?
//I have a problem inside the do-while block!
package multiplication;
import java.util.Random;
import java.util.Scanner;
/*Hey again! I've been trying to solve this problem using NetBeans environment
*
*/
public class Ypologismos
{
private int p;
private int a,b;
public Ypologismos(int a,int b,int p)
{
this.a=a;
this.b=b;
this.p=p;
}
public Ypologismos()
{
}
public void Screen()
{
System.out.println("Wrong answer ....please retry");
}
public void askForNumbers()
{
Random r=new Random();
int a,b;
a=r.nextInt(10);
b=r.nextInt(10);
int p;//p=product
p=(a*b);
System.out.println("How much is:"+" "+a+" "+"times"+" "+b+" "+"?");
System.out.println("Please insert your answer!");
Scanner s=new Scanner(System.in);
int ans;//ans=answer
ans=s.nextInt();
do
{
while(ans==p){
System.out.println("Well done!");
askForNumbers();
}
}while(ans!=p);
}
}
//and my main class ...
package multiplication;
public class Main
{
public static void main(String[] args)
{
Ypologismos application=new Ypologismos();
application.askForNumbers();
}
}
Make a terse story book of how to do it.
teach multiplication:
repeat // solving problems
int first number = something random
int second number = something random
int product = first number * second number
repeat
int answer = ask how much is first number times second number
if answer != product
say error!
until answer == product
say solved!
The above is just a first idea, not necessarily following the requirements. But it clears which loop comes in which loop and so on.
Reading your extended question
public class Ypologismos {
/** Entry point to the application. */
public static void main(String[] args) {
Ypologismos application = new Ypologismos();
application.teachMultiplication();
}
private void teachMultiplication() {
while (wantsAProblem()) {
askAProblem();
}
}
private void askAProblem() {
int αλφα = random.nextInt(10);
int βητα = random.nextInt(10);
...
}
}

Getting value to display for Java CurrentAccount class

package bankAccount;
public class CurrentAccount {
int account[];
int lastMove;
int startingBalance = 1000;
CurrentAccount() {
lastMove = 0;
account = new int[10];
}
public void deposit(int value) {
account[lastMove] = value;
lastMove++;
}
public void draw(int value) {
account[lastMove] = value;
lastMove++;
}
public int settlement() {
int result = 0;
for (int i=0; i<account.length; i++) {
result = result + account[i] + startingBalance;
System.out.println("Result = " + result);
}
return result;
}
public static void main(String args[]) {
CurrentAccount c = new CurrentAccount();
c.deposit(10);
}
}
At the moment, when I run the class, the expected System.out.println does not appear, and if I simply move public static void main(String[] args) to the top, this generates multiple red points. What is the best way for me to refactor my code so it works in the expected way?
you can have another class called Main in the file Main.java in which you can write your
public static void main(String args[])
and call
c.settlement();
in you main() to print.
Also one more advice,
in your constructor you have
account = new int[10];
which can hold only 10 ints.
in your deposit() and draw() you are not checking the account size. When the value of lastMove is more than 10 , the whole code blows up.
Hence I suggest you to use ArrayList
You never called the settlement method...
public static void main(String args[]) {
CurrentAccount c = new CurrentAccount();
c.deposit(10);
c.settlement();
}
I have the feeling that you come from some non-OOP language, like C or PHP. So some explanation:
The main method is static: that means it "exists" even when there is no object instance created, it can be thought of as if it belonged to the class instance.
on the contrary, for the other methods to "work", an instance is required.
This way the main method can be (and is actually) used as the entry point of the application
It is executed, and when it exists, (if no other threads are left running) the application terminates.
so nothing else is run that is outside of this method just by itself...
so if you don't call c.settlement(); - it won't happen...
Other notes:
Running main doesn't create an instance of the enclosing class
with new CurrentAccount(), you create an object instance, which has states it stores, and can be manipulated
be careful with arrays, they have to be taken care of, which tends to be inconvenient at times...
Why do you expect the printed output to appear? You don't actually call the settlement method, so that command is not executed.
You did not call settlement.. so nothing appears
if you add c.settlement... it is fine..
You have not called deposit() and settlement() in the main method untill you call, You cannot get expected output.

Categories