Suspending all threads took: ms warning using Threads - Android

22,236

The first line is basically saying that the garbage collector (GC) decided it needed to suspend all threads to do some of its work (such as relocating variables) and that took some time. Normally there's a number there.

The second line is the result of the collection. It freed a fair amount of memory, and you now have 1/3 of your heap free. It required your app to be paused for 2ms, and in total spent 127 ms collecting garbage.

GC in and of itself isn't bad. But if you're doing it all the time, either you're doing something with lots of memory required or you're doing something inefficiently. Heavy string parsing, especially for something like JSoup, can cause lots of small objects (mainly strings) to be made that really required cleanup quickly on a small memory device like a phone, so it isn't surprising to see here.

Basically, this is only a problem if you're getting performance hiccups from GC or if you're going OOM at some point. If neither of those are happening, I wouldn't worry about this yet.

Share:
22,236
God
Author by

God

%#%#35%#@!!

Updated on June 15, 2020

Comments

  • God
    God almost 4 years

    I have 2 Threads that make some network computation. When I run my app and after starting my second Thread I get a:

    Suspending all threads took: ms warning followed by:

    Background sticky concurrent mark sweep GC freed 246745(21MB) AllocSpace objects, 169(6MB) LOS objects, 33% free, 31MB/47MB, paused 1.972ms total 127.267ms warning.

    Sometimes I get just those 2 warnings and other times I get a lot of those 2 warnings until I decide to terminate the app running. At this point, it's just running the main Thread and basically doing nothing. Here is the relevant code:

    MainActivity.java:

    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        // Getting html page through a thread
        this.getHtmlPageThread = new GetHtmlPageThread(URL_STRING);
        this.getHtmlPageThread.start();
    
        // The thread that will search the web for data
        this.getDataFromTheWebThread = new GetDataFromTheWebThread();
    
        // Search button click listener
        searchButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                // Get the searched lyrics
                searchedLyrics = inputEditText.getText().toString();
    
                informUserAboutConnectionToTheNet();
    
                // Starting to search the web for data through a thread
                getDataFromTheWebThread.start();
    
                if (!getDataFromTheWebThread.isAlive())
                {
                    printMap(MainActivity.matchResultMap);
                }
            }
        }); // End of search button click listener
    
        printMap(MainActivity.matchResultMap);
    
    } // End of onCreate() method
    
    protected void onStart()
    {
        super.onStart();
    
        if (!this.isParseSucceeded()) // Connection to net failed
        {
            if (!getHtmlPageThread.isAlive()) // If the thread is not alive, start it.
            {
                getHtmlPageThread.start(); // Try to connect again
                this.informUserAboutConnectionToTheNet();
            }
        }
        if (!this.isParseSucceeded())
        {
            super.onStart(); // Call onStart() method
        }
    
    } // End of onStart() method
    

    GetHtmlPageThread.java:

    public class GetHtmlPageThread extends Thread
    {
        private String url;
    
        public GetHtmlPageThread(String url)
        {
            this.url = url;
        }
    
        @Override
        public void run()
        {
            try
            {
                MainActivity.htmlPage.setHtmlDocument(this.getParsedDocument(this.url));
                if (MainActivity.htmlPage.getHtmlDocument() != null)
                {
                    MainActivity.parsedSucceeded = true; // Parsed succeeded
                }
                else
                {
                    MainActivity.parsedSucceeded = false; // Parsed failed
                }
                Thread.sleep(100);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    
        /**
         * Returns the document object of the url parameter.
         * If the connection is failed , return null.
         *
         * @param url Url to parse
         * @return The document of the url.
         *
         */
        public Document getParsedDocument(String url)
        {
            try
            {
                return Jsoup.connect(url).get();
            }
            catch (IOException e) // On error
            {
                e.printStackTrace();
            }
    
            return null; // Failed to connect to the url
        }
    
    }
    

    GetDataFromTheWeb.java:

    public class GetDataFromTheWebThread extends Thread
    {
        public static boolean isFinished = false; // False - the thread is still running. True - the thread is dead
    
        @Override
        public void run()
        {
            GetDataFromTheWebThread.isFinished = false;
            try
            {
                this.getLyricsPlanetDotComResults(MainActivity.searchedLyrics); // Method for internet computations
                Thread.sleep(100);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            GetDataFromTheWebThread.isFinished = true;
        }
        ...
    }
    

    Basically the this.getLyricsPlanetDotComResults(MainActivity.searchedLyrics); method in the second Thread is doing a lot of the internet work and computations in general. More computations than net stuff to be exact.

    So I guess I got those warnings because the second Thread is too "Busy"? Or maybe just my implementation with the activity life cycle with the onCreate() method and onStart() method are wrong?

    Needless to say, I don't get the output I want, though I debugged the app and stepped through the second Thread and it works Perfectly. So again, it got to be something with my Activity's implementation.

  • God
    God about 8 years
    Ok I get it. But still, When i debug I can see my Thread is doing exactly what i want(**To update a global variable in MainActivity.java) , I just don't know when i can access it(When the Thread is done It's work) and how(Because i will need a Loop like that - while (!myThread,isAlive()) {//Do my work} , but it is a good implementation? Also i thogh about changing the Thread to HandlerThread developer.android.com/intl/zh-cn/reference/android/os/… . What do you think? Thanks.
  • Gabe Sechan
    Gabe Sechan about 8 years
    If you need to know when the thread is done, use a callback (or if you need a notification on the UI thread, a callback made from a Handler on the UI thread). HandlerThread is more for a thread where you're going to send it a series of events it has to respond to.
  • God
    God about 8 years
  • God
    God about 8 years