Running a counter thread in the background during a game - java

I am wondering the best way to keep a timer going in the background while a game is played.
I am programming a version of the HiLo game (in Java), which gives a user a certain amount of time to determine a number. If a guess is not correct, the game will tell the user whether the name is too high or too low.
I'm keeping track of time using System.currentTimeMillis() and seeing how much time has elapsed. This seems to work well, and so far I have been checking to see how much time has elapsed each time a new number is entered. For example, currently the app output looks like this:
Welcome to HiLo!
You have 10 seconds to guess a number I'm thinking of between 1 and 100.
> 67
Too high.
> 29
Too low.
Half of your time is gone! Only 5 seconds remains!
> 37
Too high.
> 33
Oops! Time is up - try again.
As you can see, currently, it can only check when I enter a new number how much time is passed.
I have tried creating a thread to start with a timer, however, when I start it, it keeps counting until the time is exhausted, without going on to the thread.run(int guess) which will be run when there is a new guess. I want to be able to still make guesses while the counter runs. Here is my attempt at a new implementation for thread.start():
public void start(int time_sent) throws InterruptedException {
time = time_sent;
startTime = (System.currentTimeMillis() / 1000);
while (1==1) {
long elapsed = ((System.currentTimeMillis() / 1000) - (startTime));
if (elapsed >= (time)) {
System.out.println("Oops! Time is up - try again.");
System.exit(0);
}
else if (elapsed >= (time/2) && !halfWarning) {
System.out.println("Half of your time is gone! Only " + (time/2) + " seconds remains!");
halfWarning = true;
}
}
}
How can I continue running this counter in the background?

This is one more approach:
public void game() {
Scanner scanner = new Scanner(System.in);
int time = 10; // sec
message("You have " + time + " seconds to guess...");
new Thread(new Background(System.currentTimeMillis() / 1000, time)).start();
while (true) {
String s = scanner.next();
if (s.equals("55")) {
message("You win");
System.exit(0);
} else {
message("try again...");
}
}
}
private void message(String str) {
System.out.println(str);
System.out.print("> "); // monit
}
You start 1 thread with behavior implemented in Background class. Next you enter while loop to capture user inputs. The Background thread works in background...
private class Background implements Runnable {
private long startTime;
private long time;
private boolean halfWarning;
private Background(long startTime, long time) {
this.startTime = startTime;
this.time = time;
}
#Override
public void run() {
while (true) {
long now = System.currentTimeMillis() / 1000;
long elapsed = now - startTime;
if (elapsed >= (time / 2) && !halfWarning) {
message("\n Half of your time is gone! Only " + (time / 2) + " seconds remains!");
halfWarning = true;
}
if (elapsed >= time) {
message("\n Oops! Time is up - try again.");
System.exit(0);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//ignore
}
}
}
}

Use a ScheduledExecutorService to execute concurrent actions in the future:
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> half = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Half of your time is gone!");
}
}, time / 2, TimeUnit.SECONDS);
ScheduledFuture<?> full = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Oops! Time is up - try again.");
// System.exit(0) ?
}
}, time, TimeUnit.SECONDS);
// check
if (input == toGuess) {
half.cancel();
full.cancel();
}

You could have a Timer thread that prints out these messages and shuts down the listening program.

It might inspire you :
public static class Game extends TimerTask {
private long start;
private long end;
public Game(long end) {
super();
this.start = System.currentTimeMillis();
this.end = end;
}
#Override
public void run() {
while (System.currentTimeMillis() - start < end)
System.out.println(System.currentTimeMillis());
}
}
public static void main(String[] args) {
TimerTask task = new Game(10000);
Timer timer = new Timer();
timer.schedule(task,0);
}

Related

Multithreading in Java findin prime number takes more time?

I tried to find out the solution of this problem but was unable to find it on StackOverflow?
I just want to know that why is my multithreadin working so slow infact it should have done opposite.
public class Prime {
static BufferedWriter writer;
static DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
public static void main(String[] args) throws IOException {
System.out.println("Without Thread" + findPrime() + " ms");
System.out.println("With thread : " + findPrimeWithThreads() + " ms");
}
public static long findPrimeWithThreads() {
Instant start = Instant.now();
int primaryNumber = 3;
while (primaryNumber <= 100000) {
int finalPrimaryNumber = primaryNumber;
new Thread(() -> {
multiplicationHelper(finalPrimaryNumber);
}).start();
new Thread(() -> {
multiplicationHelper(finalPrimaryNumber+1);
}).start();
primaryNumber+=2;
}
return Duration.between(start, Instant.now()).toMillis();
}
public static long findPrime() throws IOException {
Instant instant = Instant.now();
int primaryNumber = 3;
while (primaryNumber <= 100000) {
multiplicationHelper(primaryNumber);
primaryNumber++;
}
return Duration.between(instant, Instant.now()).toMillis();
}
public static void multiplicationHelper(int primaryNumber){
int j = 2;
boolean isPrime = true;
while (j <= primaryNumber/2) {
if (primaryNumber % j == 0) {
isPrime = false;
break;
}
j++;
}
if (isPrime) {
// System.out.println("PRIME :: " + primaryNumber);
}
}
}
This is the code and the output of the code was:
Without Thread497 ms
With thread : 22592 ms
Please can you elaborate me why is so and How to increase performance of multithreading?
I am new to multithreading programming, so am I doing something wrong in this?
"Finding prime numbers" is a compute-bound operation. It will naturally use 100% CPU utilization because it never needs to perform I/O.
The two purposes of "multithreading" are: (a) to take advantage of multiple CPU cores, and (b) to overlap computation with I/O. (And to more-easily issue parallel I/O operations.)
Multithreading can save time in the right situation, or cost considerably more time in the wrong ones.
Your very ill-considered design appears to launch 20,000 threads!
Change your function to below to
public static long findPrimeWithThreads() {
Instant start = Instant.now();
int primaryNumber = 3;
ExecutorService pool = Executors.newFixedThreadPool(4); // considering you've 4 CPU
while (primaryNumber <= 100000) {
int finalPrimaryNumber = primaryNumber;
pool.submit(()->multiplicationHelper(finalPrimaryNumber));
primaryNumber ++;
}
pool.shutdown(); // stop your threads
return Duration.between(start, Instant.now()).toMillis();
}

Print current date every 5 sec with in a 30 sec loop

The do while loop will execute for a 30 sec duration.With in that I have to print the current date in every 5 sec... For that I have written a code as below. But it is not working as expected...
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long duration = (30 * 1000);
do {
while (true) {
try {
System.out.println(" Date: " + new Date());
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} while ((System.currentTimeMillis() - startTime) < duration);
}
Other answers demonstrated doing this using while loop and Timer; here is how you can do it using ScheduledExecutorService:
private final static int PERIOD = 5;
private final static int TOTAL = 30;
...
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(() -> {
System.out.println(new LocalDate());
}, PERIOD, PERIOD, TimeUnit.SECONDS);
executor.schedule(executor::shutdownNow, TOTAL, TimeUnit.SECONDS);
Infinite loop while(true) is causing the trouble for you.
You do not need a do-while loop for this, unless it is a specific requirement.
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
long duration = (30 * 1000);
while ((System.currentTimeMillis() - startTime) < duration) {
System.out.println(" Date: " + new Date());
Thread.sleep(5000);
}
}
For do-while loop, you can just refactor as below:
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
long duration = (30 * 1000);
do {
System.out.println(" Date: " + new Date());
Thread.sleep(5000);
} while ((System.currentTimeMillis() - startTime) < duration);
}
I would use a java.util.Timer; create an anonymous TimerTask to display the Date 6 times on a five second period and then cancel() itself. That could look something like
java.util.Timer t = new java.util.Timer();
java.util.TimerTask task = new java.util.TimerTask() {
private int count = 0;
#Override
public void run() {
if (count < 6) {
System.out.println(new Date());
} else {
t.cancel();
}
count++;
}
};
t.schedule(task, 0, TimeUnit.SECONDS.toMillis(5));

How do I reset a Timer in Java?

So I'm trying to program a handheld electronic game, called Lights Out Cube, in Java using Eclipse Oxygen.2, and I decided to include a timer so that the player knows how much time was required by him to finish the game. When the player clicks on a button called "Start/Reset"(I change its text to "Reset" after clicking it once), which is where I activate the timer, the game starts. After every click I check if player has finished the game, and if he does, I stop the timer. If he wishes to play again, I want the timer to restart. Please help me out here:
//here i have a function called checkIfWinning() which does the checking; if there is a winner, the following code is executed to stop the timer
timer.cancel();
timer.purge();
//timer is a publicly declared java.util.Timer
//this is a code snippet for btnStart with "time" recording the time in seconds
time=0;
timer.schedule(new TimerTask()
{
#Override
public void run()
{
time++;
int hours = (int) time / 3600;
int remainder = (int) time - hours * 3600;
int mins = remainder / 60;
remainder = remainder - mins * 60;
int secs = remainder;
timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
}
}, 1000,1000);
Is there anyway this can be done? Or will I have to remove the timer entirely?
You can't reset when the TimerTask object will be activated, but in your specific case, you can reset the game time count without removing and recreating the timer.
Since your timer is fired every second, all you have to do is reset the time variable you are using, when the user clicks the reset button.
I am editing this answer based on Hulks and your comments:
Hulk is right, and you should use AtomicInteger for your time count. If you keep the timer running, there could be a bug some times where the value will not reset.
You can have an AtomicBoolean flag that lets the TimerTask know if the player is playing or not.
Here is a code example:
AtomicInteger time = new AtomicInteger();
//whenever you want to reset it:
time.set(0);
AtomicBoolean isPlaying = new AtomicBoolean();
//when user clicks "start":
isPlaying.set(true);
//when user wins or clicks "reset"
isPlaying.set(false);
//your timer task will look something like this:
public void run() {
if (isPlaying.get()) {
int currentTime = time.incrementAndGet();
int hours = (int) currentTime / 3600;
int remainder = (int) currentTime - hours * 3600;
int mins = remainder / 60;
remainder = remainder - mins * 60;
int secs = remainder;
timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
}
}
This might be clear.
You can't reset or pause the Timer in Java, but the functionality can be achieved by not running the Timer based on a boolean check.
As previously said by Hulk and Lev.M, AtomicInteger can be used in need of thread safety.
Whole logic in run() can be simplified using TimeUnit for converting seconds to the specified format,
time+=1000;
System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
import java.util.Timer;
import java.util.TimerTask;
public class Game
{
private static int time = 0;
private static Timer t = new Timer();
private static Game g;
private static boolean ispaused = false;
public static void main(String[] args)
{
t.schedule(new TimerTask() {
public void run()
{
if(ispaused)
{
return;
}
time++;
System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
}
}, 1000, 1000);
g = new Game();
try
{
System.out.println("Starting first game");
g.startGame(); Thread.sleep(5000); g.endGame();
System.out.println("Starting second game.");
g.startGame(); Thread.sleep(5000); g.endGame();
}
catch(Exception e)
{}
}
private void startGame()
{
time = 0;
ispaused = false;
System.out.println("Game Started");
}
private void endGame()
{
time = 0;
ispaused = true;
System.out.println("Game ended");
}
};

How do you change label text in java after a timer ticks a second passed?

I have a timer with a delay of 5 seconds. I am trying to change the label named lblTimer after a second passes to act as a countdown. I am having issues with it as currently it only works at 5 seconds. Do you have any suggestionsuggestions?
protected void Addition() {
//addition function
final int delay = 5000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
#SuppressWarnings("unused")
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
frame.getContentPane().setBackground(Color.red);
}
};
new Timer(delay, taskPerformer).start();
Random RandomNumber = new Random();
int number1 = RandomNumber.nextInt(12);
int number2 = RandomNumber.nextInt(12);
int number3 = RandomNumber.nextInt(12);
lblAnswer.setText("");
lblFirstNumber.setText(""+ number1);
lblfunction1.setText("+");
lblsecondNumber.setText(""+number2);
lblfunction2.setText("+");
lblthirdnumber.setText(""+number3);
lblequals.setText("=");
answer = number1+number2+number3;
if(delay <= 1000){
lblTimer.setText("1");
}
else if(delay == 2000){
lblTimer.setText("2");
}
else if(delay == 3000){
lblTimer.setText("3");
}
else if(delay == 4000){
lblTimer.setText("4");
}
else if (delay == 5000){
lblTimer.setText("5");
}
}
The answer to your question, that I assume is "why does this not work?", is that at no point do you recheck the elapsed time. The variable delay is always set at 5000, and never updated, also.
The stupid-ass solution:
lblTimer.setText("5");
Thread.sleep(1000)
lblTimer.setText("4");
Thread.sleep(1000)
lblTimer.setText("3");
Thread.sleep(1000)
lblTimer.setText("2");
Thread.sleep(1000)
lblTimer.setText("1");
Thread.sleep(1000)
lblTimer.setText("0");
Don't really do this, unless you need to satisfy your sick fetishes.
The four-liner
The same as above. Don't do this.
for (int i = secondsToWait; i >= 0; i--) {
lblTimer.setText(i + "");
Thread.sleep(1000);
}
The acceptable solution:
Use a Timer to schedule a task to be executed after a given period of time. You can use timers to also fire the same task multiple times at a given interval.
Timer timer = new Timer();
int secondsToWait = 5;
TimerTask task = new TimerTask() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
timer.cancel();
timer.purge();
}
}
};
lblTimer.setText(secondsToWait + "");
timer.scheduleAtFixedRate(task, 1000, 1000);
The best solution:
Instead of a timer, use a ScheduledExecutorService. This is better because of the way ScheduledExecutorService works with threads as opposed to Timer. Google it.
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
int secondsToWait = 5;
Runnable task = new Runnable() {
#Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
exec.shutdown();
}
}
};
lblTimer.setText(secondsToWait + "");
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
EDIT: As Stefan pointed out, for swing GUI applications a swing Timer would be the best pick.
It should look something like this:
1) create Timer
2) create TimerTask and implement run method (updating your count variable and check if counter is zero. if it is zero, stop the timer)
3) schedule the task to run every second
int count = [INITVALUE];
...
public void startMethod() {
final Timer timer = new Timer();
timer.shedule(new TimerTask() {
#Override
public void run() {
count--;
lblTimer.setText(count+"");
if (count == 0) {
timer.cancel();
timer.purge();
}
}
},1000);
}
Thumbs Up #Olavi Mustanoja your answer revealed an option I have never tried before now.
As he lastly suggested on his edit the javax.swing.Timer comes in very handy if you're work with GUI.
import javax.swing.Timer;
private int secondsToWait = 5000; //Time in milliseconds
private Timer timer;
....
//The following section should be inside a method member
timer = new Timer(secondsToWait, e -> {
if(secondsToWait == 0)
timer.stop();//Stop if secondsToWait is already zero
lblTimer.setText((secondsToWait/1000) + ""); //Update the label with the current sec
timer.setDelay(secondsToWait);
secondsToWait -= 1000; //Reduce time by 1sec each time
});
timer.start();
...

How to program for a stopwatch [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I found this stopwatch java code from somewhere on the Internet, but it does not seem to be working. I was wondering how to fix this code to make it work. It's supposed to have features to start, stop and reset, and should display the time as hours:minutes:seconds.milliseconds (example: 12:35:17.26). Please help me.
public class StopWatch {
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start() {
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop() {
this.stopTime = System.currentTimeMillis();
this.running = false;
}
//elaspsed time in milliseconds
public long getElapsedTime() {
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
//elaspsed time in seconds
public long getElapsedTimeSecs() {
long elapsed;
if (running) {
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else {
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
//sample usage
public static void main(String[] args) {
StopWatch s = new StopWatch();
s.start();
//code you want to time goes here
s.stop();
System.out.println("elapsed time in milliseconds: " + s.getElapsedTime());
}
}
This example shows how to start and stop a javax.swing.Timer. Several approaches to formatting are shown here. Reset is left as an exercise.
By the level of your assignment, sounds like your professor wants you to use nested loops, which are not being used in the example you took from the web.
I won't give you the full answer, but it's fairly simple: outer-most loop is for hours, the one inside hours is for minutes, the one inside minutes for seconds, and the one inside seconds for milliseconds. The inner-most loop (milliseconds), is the one that prints the current time.
Something like this:
// 24 hours in a day
for(int hours = 0; hours < 24; hours++)
{
// 60 mins in an hours
for(int minutes = 0; minutes < 60; minutes++)
{
// 60 secs in a min
for(int seconds = 0; seconds < 60; seconds++)
{
// 1000 ms in a sec.
for(int ms = 0; ms < 1000; ms++)
{
System.out.println(hours + ":" + minutes + ":" + seconds + "." + ms);
}
}
}
}
Now make it pretty and add a 1-millisecond delay in the inner-most loop and you are done! :)
If you want to make a stopwatch you must make a Thread. The Java API states all of the functions of a thread. This is necessary, because otherwise you won't be able to pause the timer. This is because the system spends the full runtime on the counting.
Also, the script you provided is used for determining the amount of time a certain calculation took, it's not ment for timing itself.
I suggest you make 2 classes, 1 for the timer and 1 for the GUI. make the GUI with a label, a start-, stop- and reset-button.
Next, make sure the timer-class EXTENDS THREAD (or implements Runnable) and make it a thread. Next implement the functions to either stop the thread or start the thread (your start/stop buttons). The Reset should be easy after that (just set the timer back to 0).
The StopWatch-class could look like this:
public class Stopwatch extends Thread
{
private long startTime;
private boolean started;
public void startThread()
{
this.startTime = System.currentTimeMillis();
this.started = true;
this.start();
}
public void run()
{
while (started)
{
// empty code since currentTimeMillis increases by itself
}
}
public int[] getTime()
{
long milliTime = System.currentTimeMillis() - this.startTime;
int[] out = new int[]{0, 0, 0, 0};
out[0] = (int)(milliTime / 3600000 );
out[1] = (int)(milliTime / 60000 ) % 60;
out[2] = (int)(milliTime / 1000 ) % 60;
out[3] = (int)(milliTime) % 1000;
return out;
}
public void stopThread()
{
this.started = false;
}
}
In the GUI-class you would make start call the 'startThread', stop call the StopWatch.stop(); (which is a Thread-function) and make reset call the reset().
This should get you started with a basic stopwatch. A (bad) example for its useage:
public static void main(String[] args) throws InterruptedException
{
Stopwatch s = new Stopwatch();
s.startThread();
while (true)
{
int[] curTime = s.getTime();
System.out.println(curTime[0] + " : " + curTime[1] + " : " + curTime[2] + " : " + curTime[3]);
}
}
It would actually be more sensible to do the calculations on the currentTimeMillis outside of the threadclass.

Categories

Resources