This method repeatedly reads commands and execute them until the game is over. The finished variable, when true, means that the player/user has hit Quit and wants to end the game - thus exiting the loop and executing till the end of the method.
import org.apache.commons.lang3.time.StopWatch;
private Parser parser;
private Command command;
private StopWatch stopWatch;
public void play()
{
stopWatch = new StopWatch();
stopWatch.start();
long timeLimit = 5000;
boolean finished = false;
printWelcome();
while (finished == false)
{
System.out.println(stopWatch.getTime() + " milliseconds");
if (stopWatch.getTime() >= timeLimit)
{
System.out.println("Time limit of " + timeLimit + " milli seconds has been reached. Good bye!");
return;
}
else
{
command = parser.getCommand();
finished = processCommand(command);
}
}
System.out.println("Thank you for playing. Good bye.");
}
But I'm observing a strange behaviour with the loop. It loops perfectly fine (displaying the continuous count of stopWatch.getTime() when the following lines are omitted :
else
{
command = parser.getCommand();
finished = processCommand(command);
}
But when I put them back in, it stops displaying the continuous incrementing time of the stopWatch as it increases towards the timeLimit (at which point, it should stop). Even if the player hasn't entered any command or input.
The stopWatch is clearly running in the background, but it doesn't display the count.
Please advise. Thanks.
Even if the player hasn't entered any command or input.
If Parser#getCommand is a method that is waiting for user input, execution will block until the user enters input. This means the while loop won't run and you won't see it printing out the new time.
Doing what you ask would make a very jarring experience for the user anyway, since it would mean that it would keep printing while they are typing in the command, and that's not very user-friendly.
You can use a producer-consumer approach for this. I have adapted the code from the linked question:
// Shared queue
final Queue<String> commands = new ConcurrentLinkedQueue<>();
// Non-blocking consumer
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// non-blocking
if((String command = commands.poll()) != null) {
processCommand(command);
}
}
}, 0, 10, TimeUnit.MILLISECONDS);
// Blocking producer (this is basically the logic from Parser#getCommand)
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
commands.add(sc.next());
}
However, this solution doesn't really let you implement the timeout. So you would have to create a new class that "wraps" the Runnable so that you can cancel it after a timeout (similar to this approach):
public class TimeOutableRunnable implements Runnable {
private final Queue<String> commands;
private final Runnable wrapped;
private volatile ScheduledFuture<?> self;
public TimeOutableRunnable(Runnable wrapped, Queue<String> commands) {
this.commands = commands;
this.wrapped = wrapped;
}
#Override
public void run() {
if(commands.isEmpty()) {
self.cancel(false);
} else {
wrapped.run();
}
}
public void runWithTimeout(ScheduledExecutorService executor, long timeout, TimeUnit unit) {
self = executor.scheduleAtFixedRate(this, 0, timeout, unit);
}
}
Then you could do:
final Queue<String> commands = new ConcurrentLinkedQueue<>();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
new TimeOutableRunnable(new Runnable() {
#Override
public void run() {
// non-blocking
while((String command = commands.poll()) != null) {
processCommand(command);
}
}
}, commands).runWithTimeout(executor, timeLimit, TimeUnit.MILLISECONDS);
I haven't tested this out and I wouldn't rate myself very high on concurrency so let me know if there is something fundamentally wrong with this approach.
I presume your parser.getCommand(); is blocking until there is input. As this while loop runs in one thread, the program is stopped at this point.
The easiest way to check if I'm right is to enter any command, and you should get some output from this line:
System.out.println(stopWatch.getTime() + " milliseconds");
You either need to implement a timeout in this method, or have a second thread counting time and interrupting the wait.
Perhaps I'm misunderstanding your question, but it sounds like your problem that it isn't printing continuously? If so, its because your parer is waiting for user input. Threading could fix this problem, run your timer and print in a seperate thread
Related
I am trying to use a scanner object to continually pass Long values to a timer. If the timer is not in use, the timer object should run for the number of seconds specified by the Long value, then print "Timer is complete". If it is already in use, the program should print "Timer already in use", and ignore the Long value. Once the timer completes the previous job, it should accept the next Long value from the scanner and begin a countdown of the specified number of seconds again. At the moment I have the code below, which just queues the jobs sequentially and waits until the timer is free before running the next one, rather than ignoring intermediary requests when the timer is busy. I have added the task.isAlive() check to help me understand what's going on, any help would be really appreciated.
Current output for scanner values 3,10,1,3:
Thread-0 is not alive.
3
Timer is done!
Thread-1 is not alive.
10
Timer is done!
Thread-2 is not alive.
1
Timer is done!
Thread-3 is not alive.
3
Timer is done!
Desired output for scanner values 3,10,1,3 (would involve removing the additional print statements currently in use for debugging)
Timer is complete // for 3
Timer already in use // for 1
Timer already in use // for 3
Timer is complete // for 10
Code:
import java.util.*;
import java.io.*;
class Timer extends TimerTask implements Runnable {
Long sleepTime;
Timer(Long inputTime) {
sleepTime = inputTime;
}
#Override
public void run() {
try {
System.out.println(sleepTime);
Thread.sleep(sleepTime * 1000);
System.out.println("Timer is complete");
} catch (InterruptedException e) {
System.out.println(sleepTime);
System.out.println("Timer already in use");
}
}
}
public class TimerMain {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
Long inpt = in.nextLong();
Runnable t = new Timer(inpt);
Thread task = new Thread(t);
if (task.isAlive()) {
System.out.format("Timer already in use");
} else {
System.out.format("%s is not alive.%n", task.getName());
task.start();
try {
task.join();
}
catch (InterruptedException e){
System.out.println("Timer already in use");
}
}
}
in.close();
}}
The problem is that you create a new Thread object in each iteration and check if isAlive on that newly created object. It will never be true as you check it before starting it.
You need to store the object between iteration. Then if the previous Thread is either null or not working, you create a new one in place of the previous one. The code could look something like this:
public static void main(String[] args){
Scanner in = new Scanner(System.in);
Thread task = null;
while (in.hasNext()) {
Long inpt = in.nextLong();
Runnable t = new Timer(inpt);
if (task != null && task.isAlive()) {
System.out.format("Timer already in use");
} else {
task = new Thread(t);
System.out.format("%s is not alive.%n", task.getName());
task.start();
}
}
in.close();
}
In my program I do have a list of n items.
I will be iterating the list and initiate a process like this:
Runtime.getRuntime.exec("cmd /C start abc.bat"+listitem() )
I need to maintain a count of 4 processes. Once any one of the process is completed, I need to start the next process , so the process count should be 4.
I am able to initiate 4 process simultaneously, but not sure on how to keep the count of 4. Basically I need some notification once a process is terminated, so I can start the next, any threading is possible.
Any help on how to implement this, can somebody share a snippet on this above requirement?
Use an ThreadPoolExecutor of size 4 and a Runnable implementation which starts the Process and then invokes Process.waitFor(). Since the thread pool will be restricted to 4 threads and all 4 threads will start a process and then wait for it, you'll be certain there won't be more than 4 child processes running.
Some sample code to help you along your way:
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(new Runnable() {
public void run() {
//use ProcessBuilder here to make the process
Process p = processBuilder.start();
p.waitFor();
}
});
public class ProcessRunner {
public static void main(String[] args) throws IOException, InterruptedException {
//Creating n threads as required
ExecutorService exec = Executors.newFixedThreadPool(4);
for(int i = 0; i < 4; i++){
exec.execute(new ProcessRunnable());
}
Thread.sleep(10000);
//whenever you want them to stop
exec.shutdownNow();
}
}
class ProcessRunnable implements Runnable{
#Override
public void run(){
do{
Process p;
try {
p = Runtime.getRuntime().exec("cd ..");
p.waitFor();
} catch (IOException e) {
//Take appropriate steps
e.printStackTrace();
} catch (InterruptedException e) {
//Take appropriate steps
e.printStackTrace();
}
}while(!Thread.interrupted());
}
}
Process#waitFor()
Causes the current thread to wait, if necessary, until the process
represented by this Process object has terminated. This method returns
immediately if the subprocess has already terminated. If the
subprocess has not yet terminated, the calling thread will be blocked
until the subprocess exits.
You should have four threads that each take an assignment from a pool, then carry it out, then when it is done, carry out the next assignment. This would be how:
class Whatever extends Thread {
public void run() {
while (!interrupted()) {
String str = listitem();
if (str == null) // there are no more commands to run
break;
Runtime.getRuntime.exec(("cmd /C start abc.bat"+str).split("\\s")).waitFor();
}
Then start four of these threads.
You can use fixed thread pool with size 4 which guarantees no more than 4 active threads at any given moment
final ExecutorService ex = Executors.newFixedThreadPool(4);
for(int i = 0; i < 100; i++) {
ex.execute(new Runnable() {
#Override
public void run() {
... run the process here and wait for it to end
}
});
}
I got an answer from my last question. But now I am unable to use and stop the Thread just after one minute after doing my things. I actually want to close/stop the thread after one minute after doing my things. So, I'm badly confused: how can I do this using:
public class Frame2 extends javax.swing.JFrame implements Runnable{
public Frame2() {
initComponents();
}
public void run(){
long startTime = System.currentTimeMillis();
while (( System.currentTimeMillis() - startTime ) < 1000) {
System.out.print("DOING MY THINGS");
}
}
}
The problem is that it is not working at all and when I close the frame containing this Thread the line of code
System.out.print("DOING MY THINGS");
works in an infinite loop.
Thanks in advance.
when I close the frame containing this Thread
Frame does not contain threads. Frame can have a reference to it. But the thread itself will run until it's execution is complete (run method ends) and not a second less.
You can not just "stop" the Thread. It must always complete it's execution (again, run method to end).
The code you wrote should be working pretty well and stop writing stuff in 60 seconds. If you want it to terminate on you closing the frame, you should add some variable to check against and write true to it when you want the thread to terminate.
Example:
private volatile boolean terminated = false;
public void run(){
long startTime = System.currentTimeMillis();
while (!terminated && System.currentTimeMillis() < startTime + 60000) {
System.out.print("DOING MY THINGS");
// here I want to do my things done in just one minute
// and after that I want to stop the thread at will!
}
}
public void stop() {
terminated = true;
}
So essentially I am concerned that my timertask's run method is not being called after 10 minutes because I am putting the main thread to sleep for 10 seconds to avoid crazy CPU usage to just run through an empty while loop all day. Here is the code for the java main method.
private static boolean testDone = false;
public static void main(String[] args)
{
final int minutes = 10;
final StressTest test = new StressTest(someParams);
test.start();
Timer timer = new Timer();
timer.schedule(new TimerTask(){
#Override
public void run() {
testDone = true;
int completedSynths = test.stop();
System.out.println("Completed Synths: " + completedSynths);
System.out.println("Elapsed Time in Minutes: " + minutes);
System.out.println("Throughput (synths/min): " + completedSynths/minutes);
}}, minutes*60*1000);
while(!testDone)
{
System.out.println("Still not done... sleeping for 10 secs....");
Thread.sleep(10000);
}
System.exit(0);
Even crazier, the System.out in the while loop is never printing. What have I done??
EDIT: TO add pseudocode for StressTest object
public class StressTest
{
private SecureRandom random = new SecureRandom();
private volatile int completedSynths = 0;
private volatile boolean shouldStop = false;
private Thread[] threads;
/**
* Instantiate a new StressTest object.
*
* #param threadCount number of concurrent threads to be polling server
*/
public StressTest(int threadCount)
{
threads = new Thread[threadCount];
}
public void start()
{
System.out.println("Starting Stress Test....");
for(int i = 0; i < threads.length; i++)
{
Runnable synthCaller = new SynthApiCaller();
threads[i] = new Thread(null, synthCaller, "SynthThread" + i);
threads[i].run();
}
}
public int stop()
{
System.out.println("Stopping Stress Test...");
shouldStop = true;
return completedSynths;
}
private String randId()
{
return new BigInteger(130, random).toString(32);
}
private class SynthApiCaller implements Runnable
{
#Override
public void run()
{
while(!shouldStop)
{
try
{
//this class makes an HTTP request to a server and then writes result to a file
MyClass.writeFile( "someFileLoc/file.data");
completedSynths++;
Runtime.getRuntime().exec("rm -r " + fileLoc);
System.out.println("Synth # " + completedSynths);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
System.out.println("Thread terminated...");
}
}
}
I am concerned that my timertask's run method is not being called after 10 minutes because I am putting the main thread to sleep for 10 seconds
The Thread.sleep(...) in your main thread will not affect the running of the Timer. If the timer is not running after 10 minutes then is it possible that test.stop() is blocking?
It is important to realize that if the test is started in the main-thread and then is being stopped in the Timer thread then some synchronization will be necessary. I assume the test is running in another thread. You probably will need it to be synchronized then inside of the Timer thread you would call something like:
synchronized (test) {
test.start();
}
If you are new to Java synchronization, there are some good tutorials online.
If you are wondering whether or not the timer is being called at all, I'd set a break point inside your timer task where is sets testDone = true and see if it gets there.
Here's a good tutorial of using a debugger in eclipse.
Even crazier, the System.out in the while loop is never printing. What have I done??
As #assylias mentioned, the System.out(...) in your while loop not showing up must mean that testDone is set to true. Since testDone is being updated and accessed in different threads, you need to make sure it is also volatile.
I just ran your code sample without the test.start() and stop() and it seems to work fine. The problem may be in your test code.
Still not done... sleeping for 10 secs....
Still not done... sleeping for 10 secs....
...
Completed Synths: 1
Elapsed Time in Minutes: 10
Throughput (synths/min): 0
Now that you've added more code, here are some comments:
completedSynths++; should be changed to be an AtomicInteger. ++ is not an atomic operation so even tho the field is volatile, multiple threads can overwrite each other's increment.
If you are trying to wait for the threads to complete, instead of sleeping for 10 minutes, I'd recommend calling thread[i].join() with the threads. Even better would be use an ExecutorService and use the awaitTermination(...) method.
You call shouldStop = true; and then return the completedSynths;. You may want to wait for the threads to finish or something.
I'd not pass in a null ThreadGroup to the Thread constructor. Just use the constructor without the ThreadGroup.
I suggest making testDone volatile. As it is, I don't see anything forcing changes to testDone to be visible to reads in threads other than the one making the change.
I'd like to write a java while loop that will iterate for 15 seconds. One way I thought to do this would be to store the current system time + 15sec and then compare that to the current time in the while loop signature.
Is there a better way?
The design of this depends on what you want doing for 15s. The two most plausible cases are "do this every X for 15s" or "wait for X to happen or 15s whichever comes sooner", which will lead to very different code.
Just waiting
Thread.sleep(15000)
This doesn't iterate, but if you want to do nothing for 15s is much more efficient (it wastes less CPU on doing nothing).
Repeat some code for 15s
If you really want to loop for 15s then your solution is fine, as long as your code doesn't take too long. Something like:
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
// do something
// pause to avoid churning
Thread.sleep( xxx );
}
Wait for 15s or some other condition
If you want your code to be interrupted after exactly 15s whatever it is doing you'll need a multi-threaded solution. Look at java.util.concurrent for lots of useful objects. Most methods which lock (like wait() ) have a timeout argument. A semaphore might do exactly what you need.
As already mentioned by other posters, if you just want the thread to pause for some time use Thread.sleep().
If you want the thread to do something, but want to make it stop after a while, use something like:
class Foo implements Runnable {
private volatile boolean killed = false;
public void run() {
while (!killed) {
try { doOnce(); } catch (InterruptedException ex) { killed = true; }
}
}
public void kill() { killed = true; }
private void doOnce() throws InterruptedException { /* .. */ }
}
and from the main thread, do:
Foo foo = new Foo();
Thread thread = new Thread(foo);
thread.start();
/* when you want to stop it */
foo.kill();
thread.interrupt();
Your general approach seems fine although you may want to see if the current time is greater than the point you want to stop, otherwise, you might be running for a long time.
The alternative is to run a timer/thread that sets a flag after 15 seconds have elapsed. This flag would have to be marked as volatile otherwise your loop might not see the change occur in the value.
The choice if you care about efficiency is which is more expensive, getting the system time once per loop or accessing a volatile variable? I don't know which one is more efficient - you could benchmark it if it's really important.
For simple, maintainable code, I'd choose the timer check approach:
long endTime = System.currentTimeMillis() + 15000
while (System.currentTimeMillis() < endTime) {
//loop
}
try this:
public class SleepMessages {
public static void main(String args[]) throws InterruptedException {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
for (int i = 0; i < importantInfo.length; i++) {
//Pause for 15 seconds
Thread.sleep(15000);
//Print a message
System.out.println(importantInfo[i]);
}
}
}
more info : here
Never check for current time in a tight loop.
Otherwise somebody with a laptop can get get his/her lap burned by an overheated CPU. I heard the stories of this actually happening.
You can use AOP and a #Timeable annotation from jcabi-aspects (I'm a developer):
#Timeable(limit = 1, unit = TimeUnit.SECONDS)
String load(String resource) {
// do this check regularly:
if (Thread.currentThread.isInterrupted()) {
throw new IllegalStateException("time out");
}
// execution as normal
}
When time limit is reached your thread will get interrupted() flag set to true and it's your job to handle this situation correctly and to stop execution.
Assuming you want the loop to do something sensible, you might find it faster to check a volatile flag. Have another thread wait 15 seconds (or use a timer) and then set it.
Alternatively, if you know roughly how long the loop body will take, run it a few hundred times, say, and do the time check in an outer loop.
final long start = System.nanoTime();
do {
for (int i=0; i<200, ++i) {
...
}
} while (System.nanoTime()-start < 15L*1000L*1000L*1000L);
System.nanoTime should not get confused by system clock changes. Use of long literal numbers is important.
You might be interested in scheduling a TimerTask that stops another thread or changes the condition of your loop.
For the java.util.concurrent approach, refer to Chapter 6 of Java Concurrency in Practice (section 6.3.7 Placing time limits on tasks, page 131).
Code example: Fetching an advertisement with a time budget.
A solution similar to #Tom Hawtin without an arbitary loop size.
final long end = System.nanoTime() + 15 * 1000 * 1000 * 1000L;
int loop = 1;
do {
for (int i=0; i<loop; ++i) {
...
}
loop++;
} while (System.nanoTime() < end);
In this case the size of the inner loop will start small but grow in size if the loop is particularly quick. If it is slow enough, it might only iterate once.
Here is my suggestion and it's working good for me :)
StoppingTime = 15 ;
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000 ;
for (int i=0; i<loop; ++i) {
// your code here
loop++;
if (((System.currentTimeMillis()/1000) - StartTime) > StoppingTime)
loop=0;
}
I would suggest you do this with the timer class avoiding the Thread.sleep(xxx); method.
for example:
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
private int globalTimer = 0;
private int limitTimer = 15;
public static void main(String[] args) {
new TimerExample();
}
public TimerExample() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
globalTimer++;
// DO YOUR CODE HERE
System.out.println("running");
if (globalTimer == limitTimer) {
timer.cancel();
}
}
}, 0, 1000);
}
}
Use an object array as your local variable to pass to the thread. In your loop check to see if that variable has been changed by your thread.
NB
Its important to use an Array Of Object since a thread's run method will be able to access it even if it was a local variable.
How?
Create a new Thread
In the run method sleep(1000*15) for 15 seconds
Update your local variable.
//The thread method
public static boolean[] delay(int seconds) {
final boolean[] cont = new boolean[1];
cont[0] = true;
Thread thread = new Thread() {
#Override
public void run() {
try {
sleep(1000 * seconds);
cont[0] = false;
} catch (InterruptedException ex) {
}
}
};
thread.start();
return cont;
}
//The loop method
public void dance(){
//here we call our delay method time it for 15 seconds.
final boolean[] delay = delay(15);
for (int i = 0; i < size; i++) {
//your code here.
if (delay[0] == false) { //check if delay has been changed to false and break.
break;
}
}
}