We are about to switch to a new forum software. Until then we have removed the registration on this forum.
So in my quest to learn, I have been playing with Threading via this Processing wiki post: Which works fine in Java. It also works fine in Android mode via the emulator, UNLESS i specify a landscape orientation.
Here's my code (which is mostly pulled from the above linked tutorial:
SimpleThread thread;
void setup()
{
orientation(LANDSCAPE);
thread = new SimpleThread(1000,"I'm a thread! ");
thread.start();
}
void draw()
{
background(255);
fill(0);
}
class SimpleThread extends Thread
{
boolean running; // Is the thread running? Yes or no?
int wait; // How many milliseconds should we wait in between executions?
String id; // Thread name
int count; // counter
// Constructor, create the thread
// It is not running by default
SimpleThread (int w, String s)
{
wait = w;
running = false;
id = s;
count = 0;
}//end SimpleThread
int getCount()
{
return count;
}//end getCount
// Overriding "start()"
void start ()
{
// Set running equal to true
running = true;
// Print messages
println("Starting thread (will execute every " + wait + " milliseconds.)");
// Do whatever start does in Thread, don't forget this!
super.start();
//run();
}//end start()
// We must implement run, this gets triggered by start()
void run ()
{
while (running && count < 10)
{
println(id + ": " + count);
count++;
// Ok, let's wait for however long we should wait
try
{
sleep((long)(wait));
}
catch (Exception e)
{
}
}
System.out.println(id + " thread is done!"); // The thread is done when we get to the end of run()
}//end run()
// Our method that quits the thread
void quit()
{
System.out.println("Quitting.");
running = false; // Setting running to false ends the loop in run()
// IUn case the thread is waiting. . .
interrupt();
}//end quit()
}//end class
Here's my console output:
debug: Starting thread (will execute every 1000 milliseconds.) I'm a thread! : 0 I'm a thread! : 1 I'm a thread! : 1 I'm a thread! : 2 I'm a thread! : 2 I'm a thread! : 3 I'm a thread! : 3 I'm a thread! : 4 I'm a thread! : 4 I'm a thread! : 5 I'm a thread! : 5 I'm a thread! : 6 I'm a thread! : 6 I'm a thread! : 7 I'm a thread! : 7 I'm a thread! : 8 I'm a thread! : 8 I'm a thread! : 9 I'm a thread! : 9 I'm a thread! thread is done! I'm a thread! thread is done!
If you comment out orientation(LANDSCAPE); or change it to orientation(PORTRAIT);, it works fine. And by that I mean you only see, say, "I'm a thread! : 1" once, instead of twice.
Any ideas why?
I'm using Processing 2.0.3 if that helps.
Answers
It's a mean trick, but setup() is actually run twice sometimes. I forget why, exactly. Something to do with setting the window and then starting over.
Anyway, you could try to add a boolean flag that checks if your thread has been created...
I have a theory: The
orientation()
function may simulate a physical device rotation, and it may not do so until the main thread has a pause. When an Android application is rotated, theActivity
is killed and re-started. If this is the case, then this is why yoursetup()
is run twice - you request a screen rotation, you start a thread, the screen rotation occurs, the activity is restarted, your old thread is still there, and then you run through it again (but the orientation is already landscape, so the cycle doesn't repeat itself...).This may very well be the case, and it could explain some of the issues that people have been having with
orientation()
. Although @TfGuy44's solution may work, I suggest that you consider trying the fix suggested in this post (it is perhaps more elegant).Note: I haven't tested this, but I have reasonable confidence in my theory.
@TfGuy44: I think that
setup()
running twice has more to do with not having thesize()
function the first call insetup()
(in Java mode, at least). I may be wrong, though...TfGuy - hmmm, that didn't work. I'll have to investigate this some more. I appreciate the advice though. Maybe the pieces are there and I can get this to work
calsign- your answer popped up as i was replying to TfGuy, so I'll go back and read it. Just wanted to edit to clarify who I was responding to
@krashe1313, your latest comment further reinforces my theory - indeed, if the activity is restarted, then your global variables are wiped as well, rendering @TfGuy44's check useless! (It was still good advice, though...)
@calsign well your method of manually changing the manifest worked. Thank you.
I do have a follow up question; if on changing the orientation of the screen is simulating a physical rotation, thus the activity gets killed then restarted, now in landscape, how can two identical instances of the same object (SimpleThread) exist with out throwing a flag that says "hey, you have 2 instances of the same object with the exact same name"?
Thanks
The two identical
SimpleThread
s are separate instances. They can both have a variable with the same name without the VM complaining. In fact, the two instances may even exist on separate Linux processes, and thus they can have no interaction (without tapping into Android's process-checking APIs).When the screen is rotated and the activity is restarted, the old activity is completely gone - it's as if the user has closed out of the sketch and restarted it. The old thread probably sticks around long enough to run its course, but the reference to it in the old activity is long gone. As far as the VM is concerned, the old thread and the new thread, although identical in code, are two completely separate threads.
For comparison, you don't encounter problems when running the same sketch twice, even though the sketch contains all of the same variables, now, do you?
Disclaimer: My understanding of the internal workings of the Android VM is far from complete, but I think my explanation should be sufficient (and sufficiently accurate) to answer your question.
@calsign Fantastic. This was my assumption, but I wasn't entirely sure. My understanding of the internal workings of Android VM, Java, Processing, life in general, etc, lol, is VERY far from complete. So thank you for taking the time to explain it.
@TfGuy44 Thanks also for your little trick. Although it didn't work in this instance, it's one I'll keep for reference.