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;
}
Related
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
I am trying to make a simple timer with uneven time intervals after each repetition.
I start as follows:
case R.id.start:
timerRuns = true;
startCycle();
break;
The cycle itself looks like this:
private void startCycle() {
pomodoroLeft = numPomodoro;
while(pomodoroLeft > 0) {
pomodoroLeft--;
actualSeconds = pomodoroLength * ONE_MINUTE;
setTimeAndRun(actualSeconds);
actualSeconds = shortLength * ONE_MINUTE;
setTimeAndRun(actualSeconds);
}
}
Method call:
private void setTimeAndRun(long timePeriod) {
runTime = timePeriod;
runnable.run();
}
And finally runnable itself:
private Runnable runnable = new Runnable()
{
public void run() {
if (timerRuns) {
runTime -= ONE_SECOND;
String str = String.format("%1$02d : %2$02d",
TimeUnit.MILLISECONDS.toMinutes(runTime),
TimeUnit.MILLISECONDS.toSeconds(runTime) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(runTime))
);
timeShown.setText(str);
mHandler.postDelayed(this, 1000);
if(timeShown.getText().toString().contentEquals("00 : 00")) {
stopClock();
//here goes the alarm.
}
}
}
};
My problem is that when I start the timer while loop seems to execute everything despite
incompliete run() of the previous method call. As a consequence timeShown TextView displays this actualSeconds = shortLength * ONE_MINUTE right away and skips 1 second each second because 2 runnables are running at the same time.
I want to achieve sequential execution here. What would be the best way to do so? Maybe implementing non-anonymous subclass and instantiate it every time would help?
Also, if you have any other suggestions that would improve my code I would greatly appreciate.
You should take a look at queues.
Here is a link to a similar question:
How to implement a queue of runnables
You should use the Executors.newSingleThreadExecutor()
http://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor%28java.util.concurrent.ThreadFactory
And here is a tutorial about the Executor:
http://tutorials.jenkov.com/java-util-concurrent/executorservice.html
here is also something that may help you understanding better multithreading in java:
Understanding multi-threading
hope this helps somehow.
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.
Hey all
I have a problem with multithreading in java. This is my scenario. I have a class,which name is LocalTime. This class should catch the current time of system, and via a method,which name is getCurrentTime, return this value to a Form. This is the code of this class
public class LocalTime implements Runnable {
private String currentTime=null;
Thread t;
private long time;
private long h;
private long m;
private long s;
public LocalTime() {
t=new Thread(this,"current Time");
t.start();
}
public synchronized void run() {
try {
for(;;){
Thread.sleep(1000);
time = System.currentTimeMillis()/1000;
h = (time / 3600) % 24;
m = (time / 60) % 60;
s = time % 60;
this.currentTime=h+":"+m+":"+s;
}
} catch (InterruptedException ex) {
Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getCurrentTime(){
return this.currentTime;
}
}
and this is the code of main form:
public MainForm1() {
initComponents();
LocalTime l=new LocalTime();
this.jLabel1.setText(l.getCurrentTime());//show the current time
//The rest of code
}
now my major problem is the jLabel1 text which shows current system time does not update each 1 second. If I insert for(;;) before the line of jLabel1.setText(l.getCurrentTime()) the rest of code won't be reacheable. what should I to correct this error? please suggest me solution with these assumptions. I know that I can run a thread in MainForm1, too but I want some solution to this problem.
The problem is that you just read the time once. You should either start a worker thread that queries LocalTime or add a listener to LocalTime that is informed of time changes and triggers the label update.
As a side note: you might want to use new Date() in conjunction with a SimpleDateFormat in order to get a nicely formatted representation.
Unless you are not including crucial pieces of code, there is no way for the label to be updated more than once.
See, your custom thread is kicking every second, updating it's own this.currentTime field.
But your label (at least with the meager amount of code that you are showing), it only gets updated once (via this.jLabel1.setText(l.getCurrentTime())) with whatever l had in it's time field at that moment.
Just because the local time thread runs, that doesn't mean it will magically go out and update the label. Why would it magically do it if you don't code that yourself? Think about it.
What you need to do is to have the thread update the label itself within it's run method. Moreover, this should be done within the Swing thread rules (and in the event queue) How you refactor that so that you get clean code, that's a topic for another thread.
// java pseudocode
public void run() {
Runnable labelUpdater = new Runnable()
{
public void run()
{
someForm.jLabel1.setText(yourUpdatedTimeFormattedAsStringOrWhatever);
}
}
try {
for(;;){
Thread.sleep(1000);
// will cause label update to occur in the awt event queue
SwingUtils.invokeLater(labelUpdater);
}
} catch (InterruptedException ex) {
Logger.getLogger(LocalTime.class.getName()).log(Level.SEVERE, null, ex);
}
}
Some notes:
You don't need the synchronized keyword in this specific instance of your run() method.
Use java.util.Calendar and java.util.Format to get string representations of the current time. What you are doing there with all that string concatenation and dividing the output of System.currentTimeMillis() is just bad. Have you looked at the Java API to see what's already there for you????????
Stuff for you to read:
Concurrency in Swing
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#event_dispatching
Concurrency (the Java Tutorial)
http://download.oracle.com/javase/tutorial/essential/concurrency/
Please, please use a Timer for that kind of task... Why go to all that extra complexity?
Try something like this:
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
final LocalTime locTime = new LocalTime();
public void actionPerformed(ActionEvent evt) {
jLabel1.setText(locTime.getCurrentTime());
}
};
new Timer(delay, taskPerformer).start();
Create a TimerTask and call the setText in timer's run method. Then schedule the task to be executed every second.
There is only one thing that u are misssing is to update the label after each second. the thread which is calculating the time by using system date is working fine. What u can do is raise an event after each second and change the value of textfield in the listener of the event.
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;
}
}
}