Use of Timer in BlackBerry project - java

I'm trying to use Timer in my BlackBerry project in this manner -
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
pushScreen(new MyScreen());
}
},200);
but I'm getting a Runtime Exception while executing the program.
Can someone please tell me what is wrong with this code? Or any other tips for using the Timer in a BlackBerry project.
My goal is to push SplashScreen for 10 sec and then MyScreen page will be open. So I want to use timer for a 10 second delay while opening the MyScreen page and during the timer I will display the SplashScreen page.

As Richard mentioned in his answer, you are having problems because you're attempting to manipulate the UI from a thread other than the main (aka "UI") thread. You just need a small change to make your code work properly:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
pushScreen(new MyScreen());
}
},
200 /* delay */,
false /* repeat = no */);
The above is the equivalent of the code you posted, for BlackBerry Java.
My goal is to push SplashScreen for 10 sec and then MyScreen page will
be open. So I want to use timer for a 10 second delay while opening
the MyScreen page and during the timer I will display the SplashScreen
page.
If this is actually what you want to do, then just make your SplashScreen appear as soon as the app is launched:
public class MyApp extends UiApplication
{
/**
* Entry point for application
* #param args Command line arguments (not used)
*/
public static void main(String[] args)
{
// Create a new instance of the application and make the currently
// running thread the application's event dispatch thread.
MyApp theApp = new MyApp();
theApp.enterEventDispatcher();
}
public MyApp()
{
// Push a screen onto the UI stack for rendering.
final SplashScreen splashScreen = new SplashScreen();
pushScreen(splashScreen);
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
pushScreen(new MyScreen());
popScreen(splashScreen);
}
},
10*1000 /* delay in msec */,
false /* repeat = no */);
}
This does what you asked, but the link that Richard provides also allows the user to dismiss the splash screen early. That may or may not be what you want, so I simply offer the alternative above.

Hard to say what exactly is going wrong, but one thing that you should not do is interact with the user interface on a thread that is not the event thread.
It won't teach you how to use timers but there is a developer article on how to do a splash screen.

You're pushing a new screen every 200 ms...
You need to kill the timer when the screen is pushed. And remember that the interval is in milliseconds, so you need to calculate that.
Good luck!

For Android you would probably want to do something like this:
initialize();
setButtonListeners();
new Thread() {
public void run() {
try {
sleep(3000);
} catch (Exception e) {
} finally {
Intent menuIntent = new Intent(SplashLoadScreen.this,
MainMenu.class);
startActivity(menuIntent);
}
}
}.start();
I'm not too familiar with BlackBerry, but it seems like you use pushScreen() instead of startActivity(), and you don't use Intents like Android does, so perhaps something as this:
initialize(); //Method to initialize all variables you might want to use.
//...Some code
new Thread() {
public void run() {
try {
sleep(3000); //Time in milliseconds
//to make this thread sleep before executing whatever other code.
} catch (Exception e) {
} finally {
pushScreen(new MyScreen()); //Push next screen
}
}
}.start();
The try{} catch(){} finally{} thing is exception handling.
Basically, if any errors happen when it's attempting to sleep for 3000 millis, then it will catch all Exceptions (a.k.a. errors) and do whatever's in catch(){}. Then, after either the try {} (if no exceptions have been found) or the catch(){} (if errors have been found) is finished, it does whatever's in the finally{}. This case finally will push the next screen.

Related

How to achieve thread concurency in Java

I am working with a Java Swing application, where I have a main frame and multiple panels which I commute between by setting them visible or not and in the same time, I am instantiating a class which is running a while loop in the background. Now, the problem is: the panels don't appear unless that while loop ends, but I would like to let the user click some buttons while the while loops continues in the background, without even him knowing about that. Here is a small example of my code:
startPage.setVisible(false);
lblError.setVisible(false);
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
QuestionPage has a while loop going, and I would like to not freeze the whole application until that is finished, but to let that while loop run in the background. So far I tried doing 2 threads by extending the Thread class, but I am not sure if this is the right way to do it.
[EDIT]
Here is my NEXT button after using a SwingWorker in order to send in background the while loop which happens in QuestionPage class and to carry on with swing operations on the main frame
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (validateInput(fieldUserID.getText(), fieldAge.getText(), fieldSex.getSelectedItem().toString(), fieldExperience.getText())) {
startPage.setVisible(false);
lblError.setVisible(false);
SwingWorker worker = new SwingWorker<Void, String>() {
#Override
public Void doInBackground() {
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
return null;
}
};
} else {
lblError.setVisible(true);
}
};
});
[ANSWER]
The trick is to use a SwingWorker to send the long running task in the background and to also call execute() on it. Here is a minimal working example for a Start button event listener:
// Send long running task in background
SwingWorker worker = new SwingWorker<Void, String>() {
#Override
public Void doInBackground() {
new QuestionPage(Integer.parseInt(fieldUserID.getText()));
return null;
}
};
worker.execute();

How to set a timer server-wide

The tile does not describe it properly so im going to try and describe it here:
I have a bukkit plugin, its a minigame.
It must have some code run for 10 minutes and then run another code until that game is finished
I currently have this:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// code for 10 minutes
}
}, 600000);
//code for after
Yet, this is only affects a single player and not that world.
So if one player joins he will wait 10 minutes and then run the otherpart of the code and so on, when the purpose is the 10 minutes start couting on their own, even if there is no player.
Thanks
Your problem is probably caused because your code is all triggered by an event?
Meaning it will only ever effect the player that triggered that event.
Instead you need a generic plugin that does not trigger on events (except for login), but instead it uses a timer and then grabs a list of all players and runs your code on each/all of them. Then after 10min it will exit to your other code and run that for the rest of the time.
Edit: rough example:
import org.bukkit.plugin.java.JavaPlugin;
public final class {$PluginName} extends JavaPlugin {
#Override
public void onEnable() { //This should proberbly be done onCommand rather than onEnable
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
long time = System.currentTimeMillis();
while (some condition....){
//load list of players
//now iterate through player list and do your code
//check if 10min has passed:
if ((System.currentTimeMillis() - time) > 600000){
//now break the loop and run your other code for the rest of the minigame
break;
}
}
//code for the rest of the minigame
while (true){
//load list of players
//now iterate through player list and do your code for the rest of the time
}
}
});
thread.start();
}
}

Delay execution of code in method Java

I want to generate random number after every 2 seconds in my java (Android) program continuously for at least 10 minutes. But I just want to pause/delay execution of code in only one method and not the whole program.
I tried using Thread like this -
boolean stop = false;
int random_number = 0;
while(true){
if(stop){ //if stop becomes true, then
return; //terminate the method
}
random_number = Math.random(); //generate random number
//which is used bu some other
//part of code
try {
Thread.sleep(2000); //delay the code for 2 secs
} catch(InterruptedException ex) { //and handle the exceptions
Thread.currentThread().interrupt();
}
}
However, this doesn't work as Thread.sleep stop the whole program execution instead on just stopping execution of code inside method and my whole screen becomes blank.
I also tried using Handler but it didn't work either as it doesn't stop execution of code in my method and instead just stack up.
This will demonstrate the working of it better -
while(true){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
System.out.println("After 2 secs"); //this gets printed
//later
}
}, 2000);
System.out.println("Before 2 secs"); //this gets printed first
}
So the code stacks up making it equivalent to using while loop and make it incredibly slow.
Also, since I'm developing app for Android, I'm running on Java SE 6, so I can't use scheduleAtFixedRate. Is there any other way in which I can accomplish this?
Thanks a lot!
private Timer timer;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Generate number
}
}, 2000, 2000);
//Documentation (From SDK)
/**
* Schedule a task for repeated fixed-rate execution after a specific delay
* has passed.
*
* #param task
* the task to schedule.
* #param delay
* amount of time in milliseconds before first execution.
* #param period
* amount of time in milliseconds between subsequent executions.
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0 || period <= 0) {
throw new IllegalArgumentException();
}
scheduleImpl(task, delay, period, true);
}
and when you want to stop it
timer.cancel()
Option 1: Using threads, you might run your job off the main (UI) thread:
new Thread(new Runnable() {
// some code here ...
// This might be in a loop.
try {
Thread.sleep(2000);
} catch(InterruptedException ex) {
// Handle ...
}
}
}).start();
Then, if this new thread you'd like to modify UI (i.e. show/hide button, display something on the screen etc), remember to pass that through the UI thread, as only this one can modify the UI. You might consider using Activity.runOnUiThread() for that.
Option 2: Another, more Android-style way of approaching that issue is to use AsyncTask. It contains three callbacks which can be used to do work on- and off- the UI thread. Sketch of such a code could look like:
private class MyTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... param) {
// This method is running off the UI thread.
// Safe to stop execution here.
return null;
}
protected void onProgressUpdate(Void... progress) {
// This methid is running on the UI thread.
// Do not stop thread here, but safe to modify the UI.
}
protected void onPostExecute(Long result) {
// Also on UI thread, executed once doInBackground()
// finishes.
}
}
Option 3: Then there is also a Timer, as suggested by #Stultuske. It's less flexible then AsyncTask, but handles the interval for you.
Depending on your needs, you can still accomplish what you seek with Handler.
You don't have to create/start the Handler in a while loop(which, as you noticed, just stacks up unless you stop the loop itself, but it is a nonsense).
Just create the Handler and tell him to post delayed your Runnable instance. In the Runnable at the very end you check your conditions. If it is still OK, then post another runnable delayed, else you do nothing and the Handler will have no more executions.
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
System.out.println("After 2 secs");
random_number = Math.random();
if (!stop) // should not be stopped, so we add another runnable;
{
handler.postDelayed(this, 2000);
}
}
handler.postDelayed(runnable, 2000);
The only downside is that Handler could freeze if the device is not used for a while, meaning it will start the counting back from where it left once the device screen is turned on.
It could do like 1 minute of correct work, then block at 1.4 seconds when the device is gone in sleep mode, and once it is turned on again, Handler would do the remaining 0.6 seconds.
Still, not knowing your needs you may be unaffected by this behavior and the answer may fit you.
if you want to use thread, do it like this :
Thread t = new Thread(){
public void run(){
while(true){
if(stop) break;
random_number = Math.random();
sleep(2000);
}
}
};
t.start();

libgdx - doing something in other thread not working

My game has a stats queue, after each game the current game stats goes into the queue.
Whenever the mainmenu starts i want to upload all the game stats to a server, and this take like 1-3 seconds and I want to do this in an other thread.
My code
#Override
public void show() {
Global.key = Global.getKey();
// System.out.println(Stats.getJSONObject(Global.key));
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
Stats.TryUploadGame1();
System.out.println("DONE");
}
});
.....
}
But this also freezes my game.
What should I do?
Your current code is posting a Runnable instance that will be executed by the render thread before the next frame. The Gdx.app.postRunnable API is generally used so background threads can ask for something to happen on the render thread. You want to post a Runnable to execute anywhere but the render thread.
As long as your Stats code doesn't interact with OpenGL context at all (since Android OpenGL APIs assume only a single thread interacts with them), you can just post your Runnable on a new background thread:
new Thread(new Runnable() { ... }).start();
This should unblock your render. (Of course, if your background thread uses a lot of CPU, it can still interfere with the render thread, but if its mostly doing blocking IO or host has spare cores, it shouldn't interfere.)
This could be improved in lots of ways (using a ThreadPool, or using Android-aware background task support), but if your stats update is relatively quick and the thread creation isn't frequent this should work fine.
Okay to do something in a other thread you need to take care of the OpenGL context. Inside of a different thread you cant do anything that does render stuff. You are forced to push such thing into the renderthread in any way. And you need to synchronize everything that can be called from the regular render thread from libgdx. For example you want to call the .act(float delta) from a stage from a different thread you are forced to put the stage indo an synchronized block.
The post runable isn't a thread. It is an runable that get executed at the beginning of the next rendercall. So it will stop the game till it's done but it is inside of the OpenGl context thread. (That's why your game stops)
So here is an example of how to use threading in libgdx. I use this inside of my game. It runs on 210 frames so 210 updatecalls per second. You can change it to as fast as possible or just to 60fps whatever you need:
public class GameLogicThread extends Thread {
private GameScreen m_screen;
private boolean m_runing;
private long m_timeBegin;
private long m_timeDiff;
private long m_sleepTime;
private final static float FRAMERATE = 210f;
public GameLogicThread(GameScreen screen) { //pass the game screen to it.
m_screen = screen;
setName("GameLogic");
}
#Override
public void run() {
m_runing = true;
Logger.log("Started");
while (m_runing) {
m_timeBegin = TimeUtils.millis();
// act of the camera
synchronized (m_screen.figureStage) { //stage with figures
// now figures
if (m_screen.m_status == GameStatus.GAME) {
m_screen.figureStage.act(1f / GameLogicThread.FRAMERATE);
}
}
m_timeDiff = TimeUtils.millis() - m_timeBegin;
m_sleepTime = (long) (1f / GameLogicThread.FRAMERATE * 1000f - m_timeDiff);
if (m_sleepTime > 0) {
try {
Thread.sleep(m_sleepTime);
}
catch (InterruptedException e) {
Logger.error("Couldn't sleep " + e.getStackTrace());
}
} else {
Logger.error("we are to slow! " + m_sleepTime); //meight create it dynamic so if you are to slow decrease the framerate till you are not to slow anymore
}
}
}
/**
* Stops the thread save<br>
*/
public void stopThread() {
m_runing = false;
boolean retry = true;
while (retry) {
try {
this.join();
retry = false;
}
catch (Exception e) {
Logger.error(e.getMessage());
}
}
}
}
This does update all my figures. To not cause any troubles with the rendering thread the figurestage is synchronized. (Kind of critical section)
Dont forget that you need to create a new thread every time you stopped it. so for example inside of the show you need todo this:
#Override
public void show() {
super.show();
m_logic = new GameLogicThread(this); //create a new one inside of the GameScreen
m_logic.start(); //start the thread
}
Also dont forget to savestop it inside of the pause stop and so on.
#Override
public void dispose() {
m_logic.stopThread();
}
According to the wiki
To pass data to the rendering thread from another thread we recommend using Application.postRunnable(). This will run the code in the Runnable in the rendering thread in the next frame, before ApplicationListener.render() is called.
So calling that method is just creating a new thread on to run on the render thread.
You may want to use standard java practice on creating threads unless this is frowned upon in libgdx because of android, that I am not sure of.

Performing two actions in order

I am creating a swing application.
It consists of calling a function with some time consuming code.
The problem is the "time consuming code" , it is called before the Label's text is set. I want the label to be set before it goes onto the next line.
Why does this occour ?
myFunction()
{
myLabel.setText("Started");
//time consuming code which creates object of another class
}
Note: I did use java.awt.EventQueue.invokeLater when starting the entire application
You should run your time consuming code in a separated thread :
myFunction(){
myLabel.setText("Started");
new Thread(new Runnable(){
#Override
public void run() {
//time consuming code which creates object of another class
}
}).start();
}
It would behoove you to learn about SwingWorker which gives you ultimate flexibility when it comes to threading. Here's the short and skinny:
All GUI actions should be on the Event Dispatch Thread (EDT for short). All time-consuming tasks should be on background threads. SwingWorker allows you to control which thread you're running code on.
First, to run anything on the EDT, you use this code:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jLabel1.setText("Yay I'm on the EDT.");
}
});
But if you want to run a time-consuming task, that won't do what you need. Instead, you'll need a SwingWorker like this:
class Task extends SwingWorker<Void, Void> {
public Task() {
/*
* Code placed here will be executed on the EDT.
*/
jLabel1.setText("Yay I'm on the EDT.");
execute();
}
#Override
protected Void doInBackground() throws Exception {
/*
* Code run here will be executed on a background, "worker" thread that will not interrupt your EDT
* events. Run your time consuming tasks here.
*
* NOTE: DO NOT run ANY Swing (GUI) code here! Swing is not thread-safe! It causes problems, believe me.
*/
return null;
}
#Override
protected void done() {
/*
* All code run in this method is done on the EDT, so keep your code here "short and sweet," i.e., not
* time-consuming.
*/
if (!isCancelled()) {
boolean error = false;
try {
get(); /* All errors will be thrown by this method, so you definitely need it. If you use the Swing
* worker to return a value, it's returned here.
* (I never return values from SwingWorkers, so I just use it for error checking).
*/
} catch (ExecutionException | InterruptedException e) {
// Handle your error...
error = true;
}
if (!error) {
/*
* Place your "success" code here, whatever it is.
*/
}
}
}
}
Then you need to launch your SwingWorker with this:
new Task();
For more info, check out Oracle's documentation: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

Categories