I'm trying to get a JProgressBar to increment by 1 every 100th of a second, and at the moment I'm using Thread.sleep(100) inside a while statement like so:
try {
while (i<=100){
doTime();
}
} catch (InterruptedException ex) {
Logger.getLogger(SplashScreen.class.getName()).log(Level.SEVERE, null, ex);
}
public void doTime() throws InterruptedException{
jLabel1.setText("sleeping");
Thread.sleep(100);
jLabel1.setText("start");
i++;
pb.setValue(i);
pb.repaint();
}
and If I debug by doing a System.out.println it displays in real time but the swing GUI freezes until it drops out of the while loop can anyone help?
thanks
matt
As derivation said, you should use SwingWorker. From its javadoc:
"SwingWorker is designed for situations where you need to have a long running task run in a background thread and provide updates to the UI either when done, or while processing. Subclasses of SwingWorker must implement the doInBackground() method to perform the background computation."
With this slight change to ProgressBarDemo.java in the java tutorial, you almost get what you want.
public Void doInBackground() {
Random random = new Random();
int progress = 0;
//Initialize progress property.
setProgress(0);
while (progress < 100) {
//Sleep for up to one second.
try {
//original code: Thread.sleep(random.nextInt(1000));
Thread.sleep(10);
} catch (InterruptedException ignore) {}
//Make random progress.
//originalcode: progress += random.nextInt(10);
progress++;
setProgress(Math.min(progress, 100));
}
return null;
}
The problem is that you are sleeping the Swing Event thread. You'll want to create a new thread for running the loop, and then have that loop update the progressbar on the swing event thread.
I would use the Swing Worker thread for the loop. Then use invokeLater for updating the progressbar.
Another good swing/thread tutorial.
Besides what derivation said, you are sleeping for 100 milliseconds. That means you are only updating every tenth of a second, not every hundredth.
If doTime() is being called within the Event Dispatch Thread (EDT), which it should since it is calling UI code (jLabel1.setText() and others), then it should not be calling sleep() at all. You do not want to freeze your UI.
The correct way of doing this is to use a timer to wake up in the correct moments (say, every 10 ms) and update the progress. The code by Jala is also a good answer, and it is the official Swing Way of doing things (timers are lower level than SwingWorkers).
Related
I am trying to make a character move for an attack then move back once the attack happens. I tried to do a thread.sleep with the first move before, then the attack and moving back after but it just effects the whole code as if it was before everything instead of being in the middle.
I checked many similar questions and none of them worked or applied to what I was looking for.
JButton btnAttack = new JButton("Attack");
btnAttack.addActionListener(new ActionListener() {
int theehp = currentehp;
int yourhp = maxhp;
public void actionPerformed(ActionEvent arg0) {
int damage = 0;
//moves to sleep
label.move(300, 50);
damage = (int) (Math.random()* 4 + 1);
theehp = theehp - damage;
ehplbl.setText(String.valueOf(theehp));
ehp.setValue(theehp);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//moves back
label.move(39,46);
if (theehp <= 0){
combat.this.setVisible(false);
clip.close();
JOptionPane.showMessageDialog(panel, "You win!");
}else{
damage = (int) (Math.random()* 2 + 1);
yourhp = yourhp - damage;
hp.setValue(yourhp);
lblhp.setText(String.valueOf(yourhp));}
if (yourhp <=0){
combat.this.setVisible(false);
clip.close();
JOptionPane.showMessageDialog(panel, "You lose!");
}
};
});
btnAttack.setBounds(39, 393, 108, 61);
panel.add(btnAttack);
Thread.sleep() will literally stop the current Thread from running anything, whatsoever, for that amount of time.
If you want other work to be done at the same time that thread is sleeping, you have to put that work on another thread. Research Executors and similar things to see how to create multiple threads and manage them properly.
Note that unless you have 2+ threads running, your program is never doing more than one thing at a time (at least in terms of business logic, a JVM does a lot in the background on its own threads).
Adding to what John Humphreys said:
The thread that calls actionPerformed(...) is the swing Event Dispatch Thread (EDT). It's the thread that handles all user input, and performs all drawing on the screen.
As John H. said, Thread.sleep() puts the calling thread to sleep. So, if you call it from within an actionPerformed() method, you are putting the EDT to sleep. Your application will be unable to respond to any user input or, to show anything happening on the screen until the sleep() returns.
I made my first game in Java - Snake,
it's main loop looks like this
while (true)
{
long start = System.nanoTime();
model.eUpdate();
if (model.hasElapsedCycle())
{
model.updateGame();
}
view.refresh();
long delta = (System.nanoTime() - start) / 1000000L;
if (delta < model.getFrameTime())
{
try
{
Thread.sleep(model.getFrameTime() - delta);
} catch (Exception e)
{
e.printStackTrace();
}
}
}
But in my project's requirments there is a responsivity point, so I need to change the Thread.sleep() into something else, but I have no idea how to do this in an easy way.
Thanks in advance for any advice.
I've done a simple game or two with Java and to handle the main game loop I've used a Swing Timer. The timer will allow you to set an ActionListener to be fired after a provided delay has elapsed. The in-between delay would be derived from your frame rate. The most basic usage would look like:
Timer timer = new Timer(delay, listener);
timer.start();
This would set the initial and in-between delays to the same value. You could also set them to be different values if needed like so:
Timer timer = new Timer(delay, listener);
timer.setInitialDelay(0);
timer.start();
In the above example, the listener will fire ASAP after starting and with a delay in-between thereafter.
A better idea is to use a Timer as suggested above which will allow you to trigger after a specified delay without calling sleep().
if you want it a little more complicated but self-made start a new Thread to handle the sleeps.
You can put pooling mechanism with some pooling frequency to avoid thread.sleep.Put your condition in while loop and wait for some tine if condition is not met.And wait time should be less so it will poll with small interval.
//more code here It is a sample code
synchronized(this) {
while (delta < model.getFrameTime()) {
this.wait(500);
}
//more code
while(!isRunning){
now = getSystemTime();
deltaTime = now - lastTime;
lastTime = now;
if(deltaTime >= 1000){
//do something
}
}
This piece of code looks awkward to me. I want the thread to "do something" every 1000 units of time, but the while loop will run infinitely before 1000 units of time passes, which wastes resoure of CPU. How do you think I could refactor this piece of pseudo code? Notice that it may be true that "do something" may take more than 1000 units of time.
PS:
I am coding using java and want a solution to the problem with Java.
Take a look at Java scheduled executors. There is a method called scheduleAtFixedRate you can use. There is a class called TimeUnit which is used in this method to make things run at certain periods. Disadvantage to this is you have to create a instanve of Callable or Runnable which is a bit clunky in my opinion
First, I would make a function just to keep track of time so the code looks cleaner. Second, if you put a sleep inside the while so we dont occupy CPU time with busy wait. You can have more timed sections with more timer variables.
int countTime(int & time){
now = getSystemTime();
deltaTime = now - time;
lastTime = now;
return deltaTime
}
...
while(!isRunning){
if(countTime(timer) >= 1000){
//do something
}
usleep(100000) // sleep so we don't occupy CPU
}
The problem here is that the code is performing a busy wait, meaning, wasting CPU cycles until delta is bigger than 1 second.
It would be better to simply sleep for a second instead, and allow other processes to take advantage of the CPU cycles while your process is doing nothing:
while(!isRunning){
doSomething();
sleep(1000); // see implementation below
}
...
void sleep(int milli) {
try {
Thread.sleep(milli);
} catch (InterruptedException e) {
// ignore
}
}
Is it going to run forever? What is the context?
Try to make it like this:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable beeper = new Runnable() {
public void run() { algorithm something here! }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 1000, 1000, TimeUnit.MILLISECONDS);
Maybe it solve your problem!
If you have some question about the methods posted above, please check the oracle documentation:
https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html
I set up a timer to perform a task every 10 seconds within a loop. Also, this is inside a broadcastReceiver, not the MainActivity.
doSomething() {
public void onSuccess(int[] arr) {
for (int i = 0; i<arr.length(); i++) {
<wait 10 seconds>
<show some message>
} // if i == 3, the loop should take 30 seconds to perform
}
}
I tried creating a new thread AND making a timer, but neither solution waits ten seconds for a task inside a loop. I have also tried doing Thread.sleep(10000) without creating a new thread, but this makes the main UI freeze for ten seconds before each task is performed. Could anyone lead me to the right direction?
Edit: this is a possible duplicate of this. My question, in other words, is that is it not possible to do a delayed task inside a loop? If so, why?
try this one count down timer http://developer.android.com/reference/android/os/CountDownTimer.html
I am preparing for interviews and just want to prepare some basic threading examples and structures so that I can use them during my white board coding if I have to.
I was reading about CyclicBarrier and was just trying my hands at it, so I wrote a very simple code:
import java.util.concurrent.CyclicBarrier;
public class Threads
{
/**
* #param args
*/
public static void main(String[] args)
{
// ******************************************************************
// Using CyclicBarrier to make all threads wait at a point until all
// threads reach there
// ******************************************************************
barrier = new CyclicBarrier(N);
for (int i = 0; i < N; ++i)
{
new Thread(new CyclicBarrierWorker()).start();
}
// ******************************************************************
}
static class CyclicBarrierWorker implements Runnable
{
public void run()
{
try
{
long id = Thread.currentThread().getId();
System.out.println("I am thread " + id + " and I am waiting for my friends to arrive");
// Do Something in the Thread
Thread.sleep(1000*(int)(4*Math.random()*10));
// Now Wait till all the thread reaches this point
barrier.await();
}
catch (Exception e)
{
e.printStackTrace();
}
//Now do whatever else after all threads are released
long id1 = Thread.currentThread().getId();
System.out.println("Thread:"+id1+" We all got released ..hurray!!");
System.out.println("We all got released ..hurray!!");
}
}
final static int N = 4;
static CyclicBarrier barrier = null;
}
You can copy paste it as is and run in your compiler.
What I want to verify is that indeed all threads wait at this point in code:
barrier.await();
I put some wait and was hoping that I would see 4 statements appear one after other in a sequential fashion on the console, followed by 'outburst' of "released..hurray" statement. But I am seeing outburst of all the statements together no matter what I select as the sleep.
Am I missing something here ?
Thanks
P.S: Is there an online editor like http://codepad.org/F01xIhLl where I can just put Java code and hit a button to run a throw away code ? . I found some which require some configuration before I can run any code.
The code looks fine, but it might be more enlightening to write to System.out before the sleep. Consider this in run():
long id = Thread.currentThread().getId();
System.out.println("I am thread " + id + " and I am waiting for my friends to arrive");
// Do Something in the Thread
Thread.sleep(1000*8);
On my machine, I still see a burst, but it is clear that the threads are blocked on the barrier.
if you want to avoid the first burst use a random in the sleep
Thread.sleep(1000*(int)(8*Math.rand()));
I put some wait and was hoping that I
would see 4 statements appear one
after other in a sequential fashion on
the console, followed by 'outburst' of
"released..hurray" statement. But I am
seeing outburst of all the statements
together no matter what I select as
the sleep.
The behavior I'm observing is that all the threads created, sleep for approximately the same amount of time. Remember that other threads can perform their work in the interim, and will therefore get scheduled; since all threads created sleep for the same amount of time, there is very little difference between the instants of time when the System.out.println calls are invoked.
Edit: The other answer of sleeping of a random amount of time will aid in understanding the concept of a barrier better, for it would guarantee (to some extent) the possibility of multiple threads arriving at the barrier at different instants of time.