Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I was digging around in some old java projects that I never finished and I pulled out this little number that is of my best projects ever built.
It's a desktop clock widget coded in java and it works perfectly fine except for one thing. The way I have it check the current time to stay updated is in a loop and the loop "crashes" in a matter of seconds so the widget no longer gets the current time.
This is how the loop is constructed (reduced in size):
public class getCurrentTime {
public static void getTime() throws InterruptedException {
int hour = global.calendar.get(Calendar.HOUR);
int minute = global.calendar2.get(Calendar.MINUTE);
if(hour == 0) {
global.hour.setIcon(new ImageIcon("resources/hours/12.png"));
}else if(hour == 23) {
global.hour.setIcon(new ImageIcon("resources/hours/11.png"));
}else {
global.hour.setText("?");
}
if(minute == 0) {
global.minute.setIcon(new ImageIcon("resources/minutes/00.png"));
}else if(minute == 59) {
global.minute.setIcon(new ImageIcon("resources/minutes/59.png"));
}else {
global.minute.setText("?");
}
Thread.sleep(1000);
getTime();
}
}
global is a class where I keep most of my variables (I know it's weird, this was like 3 years ago, it's how I used to write my programs).
So my main question is, is there a way that I can prevent the loop from "crashing"?
Thanks in advance!
This is not a loop, really. It is a recursive call. In each recursion, some more memory will be allocated, so it will after some time go out of memory. I wonder why this is a matter of seconds here, but anyway.
Try using a Timer to schedule the gui update.
Edit : you are creating a new ImageIcon in each recursion. They can be rather large in memory. Maybe they are the reason for the rapid "crash".
Apart from that I suggest sticking to java naming conventions. Class names should start with a capital letter.
Thread.sleep(1000); is not going to be a good option. You can use Timer. By using a Timer you schedule a task at regular intervals.
Timer timer = new Timer();
long interval = (1000) ; // 1 sec
timer.schedule( new TimerTask() {
public void run() {
//do your work;
}
}, 0, interval);
If you want to stop the scheduling, you can use timer.cancel();
EDIT: as Fildor said I think memory is your problem. Use timer this way, it should solve your problem.
This is first solution
class clockUpdater implements Runnable {
#Override
public void run() {
Thread.sleep(WAIT_TILL_NEW_MINUTE);
while(true){ //a infinite loop
// the Swing call below must be queued onto the Swing event thread
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
//your clock updating code here
}
});
try {
Thread.sleep(1000*60);//you only need to update once after a minute
} catch (InterruptedException e) {
// ....
}
}
}
}
This is second
class clockUpdater extends Thread{
#Override
public void run(){
Thread.sleep(WAIT_TILL_NEW_MINUTE);
while(true){
try{
//your update code here
Thread.sleep(60*1000)//
}
catch(Exception e){
//..
}
}
}
}
Note: You need to start this as soon as the minute changes in system time. Or clock time will lag behind. Calculate WAIT_TILL_NEW_MINUTE as soon as your program starts. Better to update only when it is needed.
The answer for your question is
use set timeout function for the function
which you want to avoid loop crashing.
Like:
setTimeout(function() {
// write the logic
},1000);
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I need to create a delay during my loop so that the loop only changes the color of the bossbar every 2 seconds, but I can't use Thread.sleep because that pauses the entire server and eventually crashes it. How do I create a delay like this? Surely there's just a simple 1 line method I can call to do this, I mean with Python all I have to do is type 'sleep(2)'.
If you are using bukkit try to call the scheduler to make the task run on a timer
this is a link for an in-depth explanation -> tutorial
here is some code for creating a delayed task
public void methodThatChangesBossbar() {
BukkitScheduler scheduler = getServer().getScheduler();
scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
#Override
public void run() {
//decrease bossbar health here....
//when your finished with this method just use 'return' to break the loop.
}, [put delay before each time this method runs, 2000 = 2 seconds], [offset before method first runs];
}
remember the last arguments are time expressed in milliseconds
try this
Runnable runnable2 = new Runnable() {
#Override
public void run() {
try {
Thread t = Thread.currentThread();
System.out.println("Runnable: " + t);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t = new Thread(runnable2);
t.start();
i want to terminate some process after some time if that process will not responded
i used this code but i am not able to achive the same
long start = System.currentTimeMillis(); long end = start +60000;
1 while (System.currentTimeMillis() < end)
2 {
3 Connection.execute(function); // execute
4 break; // break if response came
5 }
6 if(System.currentTimeMillis() > end)
7 {
8 close connection; // close connection if line no 3 will not responded
9 }
kindly help me on the same
As the call Connection.execute() is blocking, so main thread will be blocked until it executes, SO in that case if we want to close the connection when the main thread is blocked , we have to close connection in some other thread. May be we can use Timer & TimerTask in this case. I tried to write some code as below, May be you can some thing like that.
Timer timer = new Timer();
while (System.currentTimeMillis() < end) { //In any case, this loop runs for only one time, then we can replace it with IF condition
CloseConnectionTask task = new CloseConnectionTask(Connection);
timer.schedule(task, end); // Task will be excuted after the delay by "end" milliseconds
Connection.execute(function); // execute
task.cancel(); //If the excute() call returns within time ie. "end" milliseconds, then timerTask will not get executed.
break; // break if response came//
}
timer.cancel(); // If you have no more scheduling tasks, then timer thread should be stopped.
Below is TimerTask implementation:
class CloseConnectionTask extends TimerTask {
private Connection con;
public CloseConnectionTask(Connection con) {
this.con = con;
}
#Override
public void run() {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Note: I have one more thing to say, In your while loop, If the call to Connection.execute() successful, then you break from the loop. So what I have observed, In any case your loop is executing only once, If this is the case, then you should use IF(again its what I have seen in the provided code, you requirement may be different). Hope it may help you. If you have other thoughts on this, please share. My answer is based on this link, Good info. is there.
this way it will not help
i think you should implement thread to achieve that
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Below is the code I am working with. I am new to programming and I know I need to use a loop to have the set velocities I have repeat four times, I am just not sure how to do it. Any help would be greatly appreciated!
package Code.simpleOutput;
import edu.cmu.ri.createlab.terk.robot.finch.Finch;
public class GeoPattern {
public static void main(final String[] args)
{
Finch myFinch = new Finch();
myFinch.setWheelVelocities(255,255,1000);
myFinch.setWheelVelocities(255,0,800);
myFinch.setWheelVelocities(255,255,1000);
myFinch.setWheelVelocities(255,0,800);
myFinch.setWheelVelocities(255,255,1000);
myFinch.setWheelVelocities(255,0,800);
myFinch.setWheelVelocities(255,225,1000);
myFinch.quit();
System.exit(0);
}
}
Here's a for loop.
for(int x = 4; x >0; x--) {
myFinch.setWheelVelocities(255,255,1000);
myFinch.setWheelVelocities(255,0,800);
}
You need to explain your objective more though.
This code will set the wheel velocities to 255,255,1000, then immediately change them back to 255,0,800, and do that four times.
Aren't you instead trying to switch between them, which would require some kind of pause, timer, or test?
In the meantime, you really should peruse the Oracle documentation for Java, and in particular the control structures: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
If you are new to Java, Exceptions and Threads are probably a bit of a harsh takeoff, but bear with me:
Thread.sleep(4000);
This instruction will make your code pause for 4 seconds (it takes milliseconds as an argument).
In order to use that "pause" code, you'll need to declare that your method, here, main:
throws InterruptedException
Why? Because, if you had several "Threads" in your application, another Thread might interrupt yours while it is sleeping. Basically, say "hey, I need to calculate something, since you're asleep I'm going to borrow the processor, I'll give it back later"
Since you only have one Thread, you don't bother, you just declare that it might theorically happen, and you're good to go.
In the event that you wanted to switch the speeds and see it happen, the code becomes:
package Code.simpleOutput;
import edu.cmu.ri.createlab.terk.robot.finch.Finch;
public class GeoPattern {
public static void main(final String[] args)
throws InterruptedException // because it contains a sleep call
{
Finch myFinch = new Finch();
for(int x = 4; x >0; x--)
{
Thread.sleep(1000); // sleep a second
myFinch.setWheelVelocities(255,255,1000);
Thread.sleep(1000); // sleep another second
myFinch.setWheelVelocities(255,0,800);
}
myFinch.quit();
System.exit(0);
}
}
Are you just looking for
for (int i = 0; i < 4; i++) {
myFinch.setWheelVelocities(255,255,1000);
myFinch.setWheelVelocities(255,0,800);
}
You could use a for loop
for(int i = 0; i < 4; i++)
{
//code to repeat goes here
}
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
I need to check how many events are detected within 2 seconds. I have the timer working and I have everything else working...but I ran into a problem: the loop only checks one time, per second and I can't seem to figure out how to fix that. I need it to check constantly during these two seconds to see how many events there were in total!
Here is what I have:
int seconds = 0;
System.out.println("Seconds: " + seconds);
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {}
seconds++;
System.out.println("Seconds: " + seconds);
//This needs to be looping the whole time.
//But right now, it's being blocked and only checked once
if(eventDetected() && seconds <= 2){
events++;
}
}
So you can see my problem. I can't split them up because then the second timer would run, and THEN eventDetected() would be checked. I need it to check constantly DURING the two second timer...so I basically need both things to happen at once. Is there any way I can do this?
Thanks for any help ahead of time!
I think your design pattern needs work -- I don't know what type event you're looking to detect, but no matter how short your sleep time is, there's a chance you could miss an event using the current pattern. Here's what I suggest:
Have eventDetected() increment your events counter. That way, you won't miss an event.
Then, you just need a way to turn on and off listening (and perhaps resetting the event counter). If you're sure that in you're current pattern you are really in a different thread that won't block your eventDetected() method, you could set a flag to check. For example:
When you want to start listening:
listenForEvents = true;
In eventDetected():
if (listenForEvents) { events++; }
When you want to stop listening (for example, after your Thread.sleep() call):
listenForEvents = false;
With multithreading, make sure to watch out for concurrency issues checking and setting the variables, of course.
I would tell you what kind of event I have to keep track of but then I'd have to kill you :D
Answered my own question. Hopefully this will help anyone else out who has a similar problem at some point! I looked up multithreading a bit...
I created a new class EventTimer which implements Runnable, with a public field for seconds:
public class EventTimer implements Runnable{
int seconds;
static int timerThreadCount = 0;
Thread t;
public EventTimer() {
timerThreadCount++;
this.seconds = 0;
t = new Thread(this, "Event Timer");
t.start(); // Start the thread
}
#Override
public void run() {
// TODO Auto-generated method stub
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {
System.out.println("Waiting interupted.");
}
seconds++;
System.out.println("Seconds: " + seconds);
}
}
}
Then I used an instance of the EventTimer, and used a while loop & if statement to solve my problem.
EventTimer t = new EventTimer();
while(t.seconds < 2){
if(eventDetected()) events++;
}
It was actually quite simple! I realize that each iteration of my loop of operation (since the entire code piece above is inside an infinite loop) will create a new EventTimer thread and I will eventually run into memory problems however. How would I close/end a thread after the timer has reached 2 seconds?
I have the following code
#EventHandler
public void onPlayerQuit(PlayerQuitEvent event){
Player player = event.getPlayer();
final Player[] playerlist = getServer().getOnlinePlayers();
if (playerlist.length <=1) { // if no players are online
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
// this is a scheduler.
public void run(){
if(playerlist.length <=1){
getServer().shutdown();
}
}
}, 6000L); // runs every 6000 ticks, which is every 300 seconds, which is every 5 minutes.
}
}
Which when a player leaves, it checks to see if he was the last one on, if he was, then it after 5 minutes, it checks again, and if still no one is on its supposed to stop the server.
In this line here:
if (playerlist.length <=1) { // if no players are online
I HAVE to have it as <=1 or it doesnt work at all, but it will also stop the server if I leave, and join back and im the only one on. When I had it at =0 and just <1 it didnt work.
Any ideas?
Here is my update code (Still doesnt work):
#EventHandler
public void onPlayerQuit(PlayerQuitEvent event){
Player player = event.getPlayer();
final Player[] playerlist = getServer().getOnlinePlayers();
if (playerlist.length <=1) { // if no players are online
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
// this is a scheduler.
public void run(){
final Player[] playerlist = getServer().getOnlinePlayers();
if(playerlist.length <=1){
getServer().shutdown();
}
}
}, 500L); // runs every 6000 ticks, which is every 300 seconds, which is every 5 minutes.
}
}
The reason why what you have written does not work is your use of <=. If someone logs off and no one is left, the task is scheduled. If someone logs back on within 5 minuets or less and remains online, when the scheduled task checks to see if the server should be shutdown, 1 <= 1 is true so the server shuts down.
You mentioned that just using = did not work, this is because in boolean statements, == must be used to check for equality.
Try using this:
if (playerlist.length == 0) { // if no players are online
// Do stuff
}
Update (Discussed in comments):
I do not know the Bukkit API very well, but this is what I assume is happening then: The online player list is updated after onPlayerQuit() is executed. Try this: Inside of your onPlayerQuit() method, try checking playerlist.length == 1 and inside of your task, check playerlist.length == 0
I do not know if you have already solved this problem, but I think part of the problem is that you are trying to re-initialize an already initialized final variable...Again, like some of the others in the replies, I do not know Bukkit API as I am trying to learn it, but you cannot re-initialize a final variable...So I would either recommend taking away the final part, or if it must remain, I would make a new array for the run() method...as you are checking for a second time to see if anyone is online...it will not matter if you change arrays, because you are changing amount of players online presumably anyways...because it is final, it will always be 1 when you re-run the length of the final array of playerlist...
You code doesn't refresh the playerlist variable when the delayed task in run, never detecting if someone has joined when the task is actually run.
A better implementation of the code would be:
#EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
boolean playersOnServer = false;
for(Player p : getServer().getOnlinePlayers()) {
if(p==player) continue;
playersOnServer = true;
break;
}
if (!playersOnServer) {
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
public void run(){
//Redo players check
boolean playersOnServer = false;
for(Player p : getServer().getOnlinePlayers()) {
playersOnServer = true;
break;
}
if(!playersOnServer){
getServer().shutdown();
}
}
}, 6000L);
}
}
Inside the above code, I used a for loop instead of a simple check to see if there are any players online, to make it work with the old player array from the old bukkit, and the new collections method from the new bukkit.
This kind of detection still has its bugs, for example if the last person quits, then directly joins, and then waits 4 minutes and 59 seconds before leaving again, it will shut down the server directly when he has left.
You never cancel the task when someone logs back on. Since you never cancel the task it will execute even if someone logs back on within the 5m time frame.