0

I have a few downloads that are submitted as tasks to a ThreadPoolExecutor. Now, I am creating this ThreadPoolExecutor in a global class that extends Application. I am storing all the submitted tasks in a HashMap with ids.

I have a ListView in a Fragment. This ListView item contains pause and resume buttons. When I click on the list item itself, the download FutureTask is submitted to the global pool executor. Now, when I click on the pause button of the ListView item, I want that particular thread to pause/wait.

I have the onClick method of the pause button in my list view's custom adapter. So, when I click the button, in my adapter class, I get all the threads that are currently running, put them in an array and then get the thread with the name I want from the array. I can see in my log that the thread I want to get is running with the name I set. So once I get that thread, I do wait() on it.

In the onclick of my resume button, I notify that particular thread and set the flag to pause as false so that the thread resumes. But, the download inside that thread actually keeps running even after clicking pause. I do not know where I am going wrong.

My GlobalState Class:

public class GlobalState extends Application{

HashMap<String, Future<?>> futureMapMain = new HashMap<String, Future<?>>();

    ThreadPoolExecutor mainExec = new ThreadPoolExecutor(2, 2, 2000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new YourThreadFactory());

public void submitTaskMain(String name, Thread task){
        Future<?> longRunningTaskFuture = mainExec.submit(task);
        futureMapMain.put(name, longRunningTaskFuture);
    }

    public HashMap<String, Future<?>> getFutureMap(){
        return futureMapMain;
    }

    public ThreadPoolExecutor getMainExeutor(){
        return mainExec;
    }

public class YourThreadFactory implements ThreadFactory {
           public Thread newThread(Runnable r) {
             return new Thread(r, gettName());
           }
         }
}

My Download Method that is written inside my fragment class. gets executed on list item click:

public void abDownloadTask(){

Thread dThread = new Thread(new Runnable() {

                final Handler pdfHandler = new Handler();

                @Override
                public void run() {
                    for(something){
/* DOES SOME DOWNLOAD USING url.getcontent() with different urls in a loop and stores files to sd card. */
}
}
}
dThread.setName(threadname);
            Log.d("Tel Frag", "Thread name set as: "+dThread.getName());
            mainGs.settName(threadname);
            mainGs.submitTaskMain(threadname, dThread);
}

onclick of my pause button inside custom list adapter:

    pause.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

                needToPause = true;

                Runnable runnable = new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub

                        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
                        Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
                        Log.d("CLA", "Threads running size: "+threadArray.length); 

                        Thread neededThread = null;

                         for ( Thread thread : threadArray ){
                             Log.d("CustomListAdapter", "Thread name in array: "+thread.getName());
                                if (thread.getName( ).equals(threadname)){
                                    neededThread = thread;
                                }
                         }   

                         if(neededThread!=null){
                            while(needToPause){
                                synchronized  (neededThread) {
                                        try {
                                            neededThread.wait();
                                        } catch (InterruptedException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                }
                            }
                         } 
                    }
                };
                new Thread(runnable).start();

                notifyDataSetChanged();
        }
    });

onclick of my resume button written inside custom list adapter class:

resume.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            needToPause = false;

            Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
            Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);

             for ( Thread thread : threadArray ){
                    if ( thread.getName( ).equals(threadname) ){
                        thread.notify();
                    }
             }  


            notifyDataSetChanged();
        }
    });

I have been trying to figure it out for 2 days now but no luck. I went through a lot of examples and stackoverflow questions. I am just trying to get a thread by its name and then pause and resume it. Any help would be appreciated. Thank you!

Xcihnegn
  • 11,579
  • 10
  • 33
  • 33
Shreya
  • 241
  • 1
  • 2
  • 11
  • Your `neededThread` always seems to be null. Try writing `Log.d("test","thread is not null")` inside `if(neededThread!=null){ //here....`. Now run the app click pause button and check the `logcat` if it shows log `"test","thread is not null"` – Apurva Mar 14 '15 at 09:08
  • @Apurva: It is printing it out so my neededThread is not null for sure. Even needtopause value is true. Inside synchronized(thread), another log prints out. So it is fine till that point. But the try{} statement in which i wrote thread.wait: Any log in that try or after that try does not print. Do not understand why. Thanks! – Shreya Mar 14 '15 at 09:11

1 Answers1

0

You can't reliably use wait() and notify() on Thread objects. This is clearly stated in the Javadoc. You already have Future objects, you shouldn't be using other mechanisms anyway.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I tried canceling my tasks too. Even task.cancel() is not working. Is there a way to pause the task rather than cancel? Please comment on that question here: http://stackoverflow.com/questions/29045575/cancel-not-working-while-trying-to-cancel-tasks-in-threadpoolexecutor-android – Shreya Mar 14 '15 at 09:33
  • Is there any other reliable way to pause and resume a thread or a task/future? – Shreya Mar 14 '15 at 09:45