Site Sponsors:
Java Threads in Android 

Android Threads


Those looking to port threads to Google's Android Operating System are often frustrated: While the classic thread classes are there, using threads in your application can cause some pretty tough-to-debug problems.

Indeed, while 'googling around the 'net, one is often told not to use threads. We are told that using a Handler is better.

While using handlers is sage advice for supporting small lightweight duties, sometimes you just want to use a little thread, anyway. Indeed, as processors, battery, and RAM become less and less of an issue in our pockets, many lean-and-mean anti-thread discussions sound much like the CGA -v- VGA display-support discussions we had at Informix while writing Wingz in the early 1990's. When all is said and done, it seems that - at the moment - most technical limitations simply fade away...

The best reason why most use an honest-to-goodenss thread on android is to do heavier number crunching. By doing computer-intensive work away from the main user experience, we all know that things simply work better. (Even in user interfaces it seems, nobody likes a jerk! ;-)

Thread Hangups


Typically, one is crunching data for a reason: To eventually display something interesting. For this reason, one of the first head-scratchers we encounter when using a thread in an Android App is how it can completely trash an application. In fact, the most certain way to lock your 'App occurs whenever another Android Thread touches the GUI API in any way, shape, or form.

Consider the following:


import java.util.Timer;
import java.util.TimerTask;

public class TimeTicker extends TimerTask {

Date date = new Date();
Date dateLast = new Date();
private boolean bRunning = false;

@Override
public void run() {
dateLast = date;
date = DateX.GetToday();
if (bRunning) {
mainActivity.setDialogResult(DateX.FormatRfc822Date(date), iId);
}
}
}


In this example, our standard Java TimerTask implementation is running every second (not heavy-weight, I know - but it is the classical "hello world" example in the timer world.) Whenever we want it to send a timer event, it will do so using the setDialogResult() of mainActivity.

All well and good.

Once inside of mainActivity, we can easily update a few basic elements. When we try to invalidate the drawable surface to show the update however (a GUI function) at the time of this writing, things will go boom:


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_MARK:
{
this.vtBanner.sText = sResult;
this.invalidate(); // BOOM!
}
break;
// ...
}
}


Maddeningly, until we understand Android's thread model, the reason things suddenly go south is not readily apparent. Indeed, if we use an Android Dialog Activity, things work just fine!

By way of example, the following View.OnClickListener will update the GUI via that same setDialogResult() member function, just as easy as expected:


public void onClick(View arg0) {
dialog.bOkay = bSetValue;
this.dialog.dismiss();
if (bSetValue) {
Editable eString = dialog.editTextName.getText();
mainActivity.setDialogResult(eString.toString(), iId);
}
}


It can even Toast!


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_NEXT:
{
// Toast t = Toast.makeText(this.getContext(), sResult, 600);
// t.show();
this.vtBanner.sText = sResult;
this.invalidate(); // Works Fine!
}
break;
}
}


Why can one listener-laden Activity manage the Canvas, while even the lightest Thread, cannot?

One Thread to Draw Them All


Believe it or not, the reason why one class is blessed and another is cursed is simple: In the above example, even though the code is written as part of the main Activity class, our TimerTask is still effectively executing the code. Unfortunately, the timer running the TimerTask is not part of the main activity thread. It is another thread.

The Dialog, however, is a completely different case. Because Android Dialogs are Views, they will all share the same, common, execution thread.

Insidious, no? ( Surely knowledge is power !-)

Fortunately, the Android Framework 'wizards foresaw our dilemma: By allowing us to enqueue certain whole-life methods on-the-stack, the problem of having a non-GUI thread manage a GUI-Thread's ... uh ... gui ... is very well supported, indeed:


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_MARK:
{
this.vtBanner.sText = sResult;
this.postInvalidate(); // Another Thread = NOT thread safe!
}
break;
case BUTTON_NEXT:
{
this.vtBanner.sText = sResult;
this.invalidate(); // Another Activity = Same GUI Thread
}
break;
}
}


-We simply need to be sure that non-GUI threads never use GUI access routines directly. -It is a thread safety thing. (i.e. Even relatively speaking, providing millions of synchronizing gatekeeper operations would slow everything down. The logic here is that it is better to make the developers work a little, than to make the computer work-a-lot. (yea, that logic sounds a lot like another ancient (1970!) pro-assembly-language argument to be sure... but we like Java, C++, and C# anyway. Computers got a whole lot faster, cheaper, and better!))

Want to discuss the slow death of java.util.Vector, anyone? (--me neither :)

Executive Summary


To conclude, when it comes to using Java's classic timers & threads, we can indeed do so ... even on Android - with relative impunity. Nevertheless, when doing so we must remember to always manage those secondary threads carefully. No mater what mechanism we may cobble-together to update Android's display, we must always be sure to access that Android UI only from the main user-interface-thread!

For more information on threading and thread-related issues, you can read more under the painless threading topic on the Android Developer's Site.

[ add comment ] ( 3327 views )   |  permalink
Unit Testing Today 
In 2009 and 2010, the United States Army asked me to write several papers on modern software capabilities.

Inspired by what I discovered on recent unit testing advancements, I have written an article on unit testing. One that I would like to share:

[ Unit Testing Today ]

While the observations in the above focuses a little more on .NET & Microsoft software developer tools than I would prefer, I believe that this paper has a little something for everyone.

Enjoy!



[ add comment ] ( 2294 views )   |  permalink
Java Processes - Java Jive? 

NOTE:


Our quest to find an elegant solution to the random Platform / Process hang-up (zombie) read-problem lead to the creation of an Open-Source Project.


Cross-platform and easy to re-use, you will recognize some of the following code as par for the Microsoft Windows & POSIX / Linux Test Cases of the IpcReader Project!

--- ORIGINAL OBSERVATION ---


Common Problem


It should have been noticed well before now - but since it is a problem, it should be documented. That way someone can fix it.

The Story


Because 3rd party code tends to break over time, I have been contemplating putting together a few Java 'wrappers' around some strategic external commands. Shelling out to do things like FTP, TAR (etc.) could come in very handy!

Though implementations can differ wildly, wrapping external commands would be far more stable over the eons. -Certainly across the desktops I like to write software for (i.e. Linux, Mac, & Windows.)

The Code


So after trying the 'old' way of starting a command from Java:

Process proc1 = Runtime.getRuntime().exec("ps ax");


-We noticed that trying to do such for a genuine external command, simply did not work on Ubuntu (at least, nut under my current 1.6 version of the Sun/Oracle JVM). While everything seems to run just-fine, trying to read a stream from an executed external command winds up hanging any read-operation in a forever-loop:

Process proc2 = Runtime.getRuntime().exec("/bin/tar");


So what's a good geek to do? -Why, ask other enthusiasts, of course.

Thanks, Stack Overflow!


After scanning over a decade's worth of 'solutions' to the 'we cannot read the process stream' problem, I decided to create the definitive example. An all-in-one class. A single demonstration that incorporated every approach proposed by every-one I could 'google-to.

Here is the best thread:

[ Community Observations ]

Of course I posted the approach at a few places. But I was pleased to get so many interesting responses in so short a time from StackOverflow.

Bottom Line


To save you some reading-time, lets summarize by noting that sometimes using

Process proc3 = new ProcessBuilder("/bin/tar").start();


-is better. Curiously however, sometimes using

Runtime.getRuntime().exec("/bin/tar");


works just as well.

Of the two approaches, we have noted on our platform that while ProcessBuilder fails to recognize 'internal' shell commands, on my machine using ProcessBuilder gives the best results. For me & for now, only ProcessBuilder will properly invoke those external commands.

Conversely, when wanting to run those exact same internal commands, at the time of this writing that classic toolkit is by far the easiest way-to-go. (i.e. No need for scripting, invoking sub-shells, writing daemons, channeling druids, etc.)

'Der Code


Until our various JDK 'gurus catch up with this observation, allow me to share the following code. -Something everyone might quickly try for themselves:


package Problems;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RunningProblem {

public static class RunningReader implements Runnable {

private Process proc;
private String sName;

private RunningReader(Process proc1, String sName) {
this.proc = proc1;
this.sName = sName;
}

public void run() {
try {
InputStreamReader in = new InputStreamReader(proc.getInputStream());
BufferedReader reader = new BufferedReader(in);

String line = reader.readLine();
while (line != null) {
System.out.println(sName + ": " + line);
line = reader.readLine();
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
try {
Runtime rt = Runtime.getRuntime();

Process proc1 = rt.exec("ps ax");
RunningReader reader1 = new RunningReader(proc1, "reader1");

Process proc2 = rt.exec("ls -l /");
RunningReader reader2 = new RunningReader(proc2, "reader2");

Process proc3 = rt.exec("/bin/tar");
RunningReader reader3 = new RunningReader(proc3, "reader3");

pool.execute(reader3);
pool.execute(reader2);
pool.execute(reader1);

} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
pool.shutdown();
}
System.out.println("Launcher.main() Exited.");
}
}


Conversely, here is the latest way to do the same thing using ProcessBuilder:


Process proc1 = new ProcessBuilder("ps ax").start();
RunningReader reader1 = new RunningReader(proc1, "reader1");

Process proc2 = new ProcessBuilder("ls -l /").start();
RunningReader reader2 = new RunningReader(proc2, "reader2");

Process proc3 = new ProcessBuilder("/bin/tar").start();
RunningReader reader3 = new RunningReader(proc3, "reader3");


-Just paste those six lines over their classic equivalent, after trying it.

RFC


If you can take a moment to comment on this thread after trying the above, then we can all learn what-works on which-platform someday.

May the source be with you... Always!


--Rn


[ add comment ] ( 1784 views )   |  permalink  |  related link

<<First <Back | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Next> Last>>