【问题标题】:wait() method on thread not working Android线程上的wait()方法不起作用Android
【发布时间】:2015-03-14 08:43:28
【问题描述】:

我有一些下载作为任务提交给ThreadPoolExecutor。现在,我在一个扩展 Application 的全局类中创建了这个 ThreadPoolExecutor。我将所有提交的任务存储在带有 ID 的 HashMap 中。

我在Fragment 中有一个ListView。这个ListView 项目包含暂停和恢复按钮。当我单击列表项本身时,下载FutureTask 被提交给全局池执行器。现在,当我单击 ListView 项目的暂停按钮时,我希望该特定线程暂停/等待。

我的列表视图的自定义适配器中有暂停按钮的onClick 方法。因此,当我单击按钮时,在我的适配器类中,我获取当前正在运行的所有线程,将它们放入一个数组中,然后从数组中获取具有我想要的名称的线程。我可以在我的日志中看到我想要获取的线程正在以我设置的名称运行。所以一旦我得到那个帖子,我就会在上面做wait()

在我的恢复按钮的onclick 中,我通知该特定线程并将标志设置为 false,以便线程恢复。但是,即使在单击暂停后,该线程内的下载实际上仍会继续运行。我不知道我哪里错了。

我的 GlobalState 类:

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());
           }
         }
}

在我的片段类中编写的我的下载方法。在列表项单击时执行:

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);
}

在自定义列表适配器中点击我的暂停按钮:

    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:

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();
        }
    });

我已经尝试了 2 天,但没有运气。我经历了很多例子和stackoverflow问题。我只是想按其名称获取一个线程,然后暂停并恢复它。任何帮助,将不胜感激。谢谢!

【问题讨论】:

  • 您的neededThread 似乎总是为空。尝试在if(neededThread!=null){ //here.... 中写入Log.d("test","thread is not null")。现在运行应用程序单击暂停按钮并检查logcat 是否显示日志"test","thread is not null"
  • @Apurva:它正在打印出来,所以我需要的线程肯定不为空。甚至需要暂停值也是如此。在 synchronized(thread) 内部,打印出另一个日志。所以到那时为止都很好。但是我在其中编写 thread.wait 的 try{} 语句:该 try 或该 try 之后的任何日志都不会打印。不明白为什么。谢谢!

标签: java android multithreading wait threadpoolexecutor


【解决方案1】:

您不能可靠地在 Thread 对象上使用 wait()notify()。这在 Javadoc 中有明确说明。您已经拥有Future 对象,无论如何您都不应该使用其他机制。

【讨论】:

  • 我也试过取消我的任务。甚至 task.cancel() 也不起作用。有没有办法暂停任务而不是取消?请在此处评论该问题:stackoverflow.com/questions/29045575/…
  • 还有其他可靠的方法来暂停和恢复线程或任务/未来吗?
猜你喜欢
  • 2013-04-18
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多