Is it possible to get a list of all threads currently running on an Android device?
I am using Android studio and I have created two Android projects.
In the first app I created a dummy threads.
#Override
protected void onCreate(Bundle icicle) {
Thread t = new Thread("DummyTHREAD")
{
public void run() {
while(true) {
// yield();
}
}
};
t.start();
In the second app I want a thread list including the dummy thread from App one. I have tried already the following:
java.util.Map<Thread, StackTraceElement[]> myMap = Thread.getAllStackTraces();
Then I started the first app and debugged the second app afterwards, but this just show me the system threads and the main thread of my second application.
Can anybody help me?
Related
Before I start: I'm a newbee in JavaFX and with this project i want to learn how to use this library properly.
The situation is the following: i have a server-client application. The server sends the client a list of the active users on the server. Now i want to list the active users in the UI. I wanted to do that with buttons in FlowPane. The problem is that my client is in an external thread, so not in the application-thread. But because of the fact that the client gets the list on users, I tried to update the button-list directly from the client-thread.
if(data.getObject() instanceof ArrayList<?>) {
ArrayList<User> activeUsers = (ArrayList<User>) data.getObject();
controller.setActiveUsers(activeUsers);
}
The method in my controller does the following:
public void setActiveUsers(ArrayList<User> activeUsers) {
for(User user:activeUsers) {
fpOnlineUsers.getChildren().add(new Button(user.getName()));
}
}
The Exception i get is the following:java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
I have two questions:
How can i fix this?
Why blocks JavaFX changed made from threads other than the application-thread?
Please apologize any language mistakes, I'm not a native speaker :)
You need to make any JavaFX object related calls on the Application Thread. To do this from your client Thread use the Application.runlater(Runnable) function.
Your code should look something like this:
public void setActiveUsers(ArrayList<User> activeUsers) {
Platform.runLater(new Runnable() {
#Override public void run() {
for(User user:activeUsers) {
fpOnlineUsers.getChildren().add(new Button(user.getName()));
}
}
}
});
Reference:
Platform.runLater and Task in JavaFX
I'm new to Android and Java. I'm trying to download 1000 plus images. I don't want to do that serially in a UI thread as that will be slow. Hence, I implemented multi-threading using thread and runnable in the below manner.
The for-loop will be called 1000 plus times. So is it an efficient way of achieving it? Will the OS manage the thread pool by its own?
private void syncS3Data() {
tStart = System.currentTimeMillis();
try {
for (final AWSSyncFile f : awsSyncData.getFiles()) {
new Thread(new Runnable() {
#Override
public void run() {
beginDownload(f);
}
}).start();
}
} catch (Exception ex) {
progressDialog.dismiss();
showMessage("Error:" + ex.getStackTrace().toString());
}
}
for Sure you can't do that in MainThread (UI Thread) because if you did, the application will not be responding.. and then it will be killed by system, you can use AsyncTask class in order to do what do you need but i prefer to use intentservice
However you have to use Intentservice it's a worker thread (long operation) but be noted intentservice will not execute anything until it finish the current task, if you need to download it in parallel then you have to use Service it works with UI Thread so you need asyncTask in order to perform the action but make sure of calling stopSelf() unlike intentService it will be stopped once it finish
Instead of creating threads for each download, create one thread and use that for downloading all images.
You can use AsyncTask Refer: https://developer.android.com/reference/android/os/AsyncTask.html
private class DownloadFilesTask extends AsyncTask<SomeObject, Integer, Long> {
protected Long doInBackground(SomeObject... objs) {
for (final AWSSyncFile f : obj.getFiles()) {
beginDownload(f);
}
}
protected void onPostExecute(Long result) {
//Task Completed
}
new DownloadFilesTask().execute(someObj);
I had developed an e-commerce app before and have encountered a similar problem in which I had to download some 200+ images for each category.The way I did it was using a loop within an AsyncTask and after each download was completed the image was displayed at the relevant place using the onProgessUpdate() function.I can't share the actual code,so i will give a skeleton example.
public class DownloadImages extends AsyncTask<String,String,String>
{
File image;
protected String doInBackground(String... params)
{
//download the image here and lets say its stored in the variable file
//call publishProgress() to run onProgressUpdate()
}
protected void onProgressUpdate(String... values)
{
//use the image in variable file to update the UI
}
}
I have a code that worked very good. But when i run several it, my app crashes for this error:
03-24 14:47:34.542 3489-3546/com.example.com E/AndroidRuntime﹕ FATAL EXCEPTION: pool-4-thread-1
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
My code:
public class Sample {
public Sample(Context context) {//error for this line
mContext = context.getApplicationContext();}
public void doSignUp( String firstName, String lastName, String userName) {
//some code for signup users
}
}
public class Service {
Runnable task = new Runnable() {
#Override
public void run() {
Sample sample = new Sample(getApplicationContext());
Sample.doSignUp(firstName,lastName,userName);
decreaseCounter();
if(getCounter() <= 0){
stopSelf();
}
}
};
Your problem is that you are probabley trying to update a UI componenet from a background thread (That is-a thread that does not run on the main thread - or "The UI thread" asyou will probabley read on other places), in order to achieve that you should pass a "Handler" that was created on either activity or a fragment (or something else that got created on the Main\UI thread) since the handler is connected to WHERE IT WAS CREATED it will act as a "bridge" between the two thread.
The error you are getting is from the OS, That Looper object is the one responsible to "push" tasks to the main\ui thread task queue.
You can also use asynctask that will essentially do the above for you.
I have a code in the UI Thread that call to another Thread. This new Thread wait for a server response to execute an database update.
When the new Thread send the post content the server send the answer fine, but the update process to the database stops when the screen (activity) load the next item to calculate and send it to the server again.
My code looks like this
public class MyActivity extends Activity {
onCreate(){ ... }
public void pushButton(View v) {
...
//Call the Thread
MyOwnThread t = new MyOwnThread(arg1, arg2);
t.start();
showTheNextItemToProcess();
}
}
MyOwnThread looks like this
public class MyOwnThread extends Thread {
public MyOwnThread(String arg1, Object arg2) { ... }
public void run() {
if(arg1.equals("ok_status") {
//The code on this part stops wen the UI Thread show the next item to process
for( ... ) {
// ...
}
}
}
}
I tried with send a clone of the variables inside the new Thread constructor, but the result it's the same. I don´t know why the UI Thread interrupts the another Thread. With the ListenableFuture (Google Guava) it´s the same.
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> futureTask = service.submit(new Callable<String>(){
public String call() {
//Send the post to the server
}
});
Futures.addCallback(futureTask, new FutureCallback<String>() {
#Override
public void onSuccess(String arg0) {
//when get the answer from the server, executes the db update
//the UI thread stop this too
}
});
I don't see errors in the LogCat. Your help is welcome, sorry for my bad english.
Thanks!
EDIT
I changed my code to use full threads (extends Thread), with WIFI connection the app sends the package to the server and the server returns the response, the app takes the value sended from the server and trigger the db update, it's fine!. But with the movil data (local operator), the app calls and runs the Thread but the thread simply not continue running. I had set the priority to MAX and it's the same. Anyone know why????
Thanks!
I am working on an app that implements a custom ListView that contains images. I was able to get the listview to download and cache the images, but I would like to move the downloading onto a separate thread. To do so, I created a CachedLogoDownloader class who's goal is to asynchronously download the images and save them in memory to be accessed later by the custom Adapter class.
The problem is that the thread holds up the entire UI. Even when the code in the run() was just a "thread.sleep()" the UI stopped whenever the request for a logo image occurred. Similarly, placing an infinite loop in the run() caused the program to hang indefinitely.
class CachedLogoDownloader{
private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();
Context context;
ArrayList<String> FIDs;
Thread runner;
public CachedLogoDownloader(Context inContext){
this.context = inContext;
//list of company logos (by FID) to be downloaded
FIDs = new ArrayList<String>();
//asynchronous downloader thread (single thread for lower-end devices. Shouldn't be much slower to get the images, though)
runner = new Thread(new Runnable() {
public void run() {
for(String FID:FIDs){
Log.d(Cloud.DEBUG_TAG, "Icon Runnable for: " + FID);
Bitmap tempImage = Cloud.lookupIcon(context, FID);
cache.put(FID, tempImage);
FIDs.remove(FID);
}
}
});
}
public Bitmap getLogo(Company aCompany){
String currentFID = aCompany.getFID();
//if the image has already been cached, return the cached image
if(cache.containsKey(currentFID))
{
return cache.get(currentFID);
}
else
{
//add the logo to the list of logos to be downloaded
FIDs.add(currentFID);
//if the downloader thread completed (or hasn't started yet) make it download stuff.
if(!runner.isAlive()){
runner.setPriority(Thread.MIN_PRIORITY);
runner.run();
}
//return null for now (until next time, whent the image will be in the cache!.)
return null;
}
}
}
runner.run();
That is not starting a separate thread, but just executing the contents of the run method on the calling thread. You probably want
runner.start();
Also, you cannot start a Thread more than once, so
if(!runner.isAlive()){
this check is probably not very useful. Start the thread when you need the image (or when you start the application), and then just wait for it to do its work. If you need more complex logic, such as thread pooling or error handling, you should probably just use a library for asynchronous image loading.