AsyncTask的一直等待? [英] AsyncTask keeps waiting?

查看:114
本文介绍了AsyncTask的一直等待?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的活动之一的按钮调用,更新底层光标的ListView的SimpleCursorAdapter的AsyncTask的。每次我按一下按钮,为AsyncTask的一个新的线程,并将该任务完成(进入等待状态)。如果我按一下按钮5次以上,5 AsyncTasks结束与等待的状态坐在那里。这是正常的还是我有内存泄漏的地方?

的AsyncTask的

 私有类updateAdapter扩展的AsyncTask<虚空,虚空,虚空> {

    @覆盖
    保护无效doInBackground(虚空...... PARAMS){
        //打开数据库连接
        如果(_db == NULL || _db.isOpen()!)_db =新DatabaseWrapper(ActivityShowWOD.this).getWritableDatabase();
        光标WODcursor;

        //检查是否wod_id设置
        如果(_wod_id == -1){
            //抓住从preferences,并在同一时间构建SQLselection字符串过滤器
            共享preferences preFS = getShared preferences(preferences,0);
            的String [] filterNames = getResources()getStringArray(R.array.filters_values​​)。
            布尔[] filterValues​​ =新的布尔[filterNames.length]
            字符串SQLselection =;

            的for(int i = 0; I< filterNames.length;我++){
                filterValues​​ [I] = prefs.getBoolean(filterNames [I]中,假);

                //生成SQL查询
                如果(filterValues​​ [我] ==真){
                    SQLselection + = filterNames [I] += 1或+ filterNames [I] += 0;
                } 其他 {
                    SQLselection + = filterNames [I] += 0;
                }

                //添加一个AND,如果有更多的过滤器
                如果(I< filterNames.length  -  1)SQLselection + =和;
            }

            //获取匹配滤波preferences所有WODs
            WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS,
                                      新的String [] {DatabaseConstants.WORKOUTS_ID,DatabaseConstants.WORKOUTS_NAME,
                                                     DatabaseConstants.WORKOUTS_NOTES,DatabaseConstants.WORKOUTS_CFID},
                                      SQLselection,NULL,NULL,NULL,NULL);

            //将光标移动到一个随机位置
            随机兰特=新的随机();
            WODcursor.moveToPosition(rand.nextInt(WODcursor.getCount()));

            //商店wod_id
            _wod_id = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_ID));
        } 其他 {
            //获取光标从wod_id
            WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS,
                                 新的String [] {DatabaseConstants.WORKOUTS_ID,DatabaseConstants.WORKOUTS_NAME,
                                                DatabaseConstants.WORKOUTS_NOTES,DatabaseConstants.WORKOUTS_CFID},
                                 DatabaseConstants.WORKOUTS_ID +=+ _wod_id,NULL,NULL,NULL,NULL);

            WODcursor.moveToFirst();
        }

        //商店WOD信息转化为类的实例变量和关闭游标
        _wod_cfid = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_CFID));
        _wod_name = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NAME));
        _wod_notes = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NOTES));
        WODcursor.close();

        //返回有关这一WOD所有练习
        _excCursor = _db.query(DatabaseConstants.TBL_EXERCISES,
                              新的String [] {DatabaseConstants.EXERCISES_ID,DatabaseConstants.EXERCISES_EXERCISE,
                                             DatabaseConstants.EXERCISES_REPS,DatabaseConstants.EXERCISES_NOTES},
                              DatabaseConstants.EXERCISES_WOD_ID +=+ _wod_id,NULL,NULL,NULL,
                              DatabaseConstants.EXERCISES_ID +ASC);
        返回null;
    }

    @覆盖
    保护无效onPostExecute(无效的结果){
        _adapter.changeCursor(_excCursor);
        _adapter.notifyDataSetChanged();
        _WODlist.setOnItemClickListener(新WODlistClickListener());
    }

}
 

和code在我的onCreate调用任务(该活动第一次加载时):

  upAdapter =新updateAdapter()执行()。
 

而在按钮onClickListener:

  //重置wod_id
            _wod_id = -1;

            //更新底层SimpleCursorAdapter
            upAdapter =新updateAdapter()执行()。
 

在AsyncTask的之一的堆栈跟踪(这是适用于所有的人):

 的Object.wait(长,INT)行:不可用[本地方法]
Thread.parkFor(长)线:1535
LangAccessImpl.parkFor(长)线:48
Unsafe.park(布尔型,长)线:317
LockSupport.park()线:131
的AbstractQueuedSynchronizer $ ConditionObject.await()线:1996
LinkedBlockingQueue.take()线:359
ThreadPoolExecutor.getTask()线:1001
ThreadPoolExecutor.runWorker(的ThreadPoolExecutor $工人)线:1061
的ThreadPoolExecutor $ Worker.run()线:561
Thread.run()线:1096
 

解决方案

的AsyncTask 引擎盖下使用<一个href="http://developer.android.com/reference/java/util/concurrent/ThreadPoolExecutor.html"><$c$c>ThreadPoolExecutor.这些线程可能不走了一会儿,因为它会是一种浪费,保持创建和拆除这些线程过于频繁。过了一段时间,如果你创造更多的 AsyncTasks ,你会发现它会停止创建新的线程,它会重新使用旧的。

更新,以解决一些细节:

您会认为,如果有空闲的线程池,它不会建立新的,但是这并不完全正确。想法是,有一定数目的是有大约保持处理异步任务有用线程。这就是所谓的芯池大小。在Android的的AsyncTask 情况下,他们似乎已经将它设置为5。如果你看的的ThreadPoolExecutor 的文件,它说

  

在新任务提出的方法execute(Runnable接口),并且比corePoolSize线程较少的运行,一个新的线程被创建来处理请求,即使其他辅助线程是空闲的。

还有一个最大恰当地称为最大池大小。

A button in one of my activities calls an AsyncTask that updates the underlying Cursor for a ListView's SimpleCursorAdapter. Everytime I click the button, a new thread for the AsyncTask is added and the task completes (goes to 'wait' status). If I click the button 5 or more times, 5 AsyncTasks ends up sitting there with 'wait' status. Is this normal or do I have a memory leak somewhere?

The AsyncTask

private class updateAdapter extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        // Open database connection
        if(_db == null || !_db.isOpen()) _db = new DatabaseWrapper(ActivityShowWOD.this).getWritableDatabase();
        Cursor WODcursor;

        // Check if a wod_id is set
        if(_wod_id == -1) {
            // Grab filters from preferences and at the same time build SQLselection string
            SharedPreferences prefs = getSharedPreferences("Preferences", 0);
            String[] filterNames = getResources().getStringArray(R.array.filters_values);
            boolean[] filterValues = new boolean[filterNames.length];
            String SQLselection = "";

            for (int i = 0; i < filterNames.length; i++) {
                filterValues[i] = prefs.getBoolean(filterNames[i], false);

                // Build SQL query
                if(filterValues[i] == true) {
                    SQLselection += filterNames[i] + " = 1 OR " +  filterNames[i] + " = 0";
                } else {
                    SQLselection += filterNames[i] + " = 0";
                }

                // Add an "AND" if there are more filters 
                if(i < filterNames.length - 1) SQLselection += " AND ";
            }

            // Get all WODs matching filter preferences 
            WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS, 
                                      new String[] { DatabaseConstants.WORKOUTS_ID, DatabaseConstants.WORKOUTS_NAME,
                                                     DatabaseConstants.WORKOUTS_NOTES, DatabaseConstants.WORKOUTS_CFID }, 
                                      SQLselection, null, null, null, null);

            // Move the Cursor to a random position
            Random rand = new Random();
            WODcursor.moveToPosition(rand.nextInt(WODcursor.getCount()));

            // Store wod_id
            _wod_id = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_ID));
        } else {
            // Get the cursor from the wod_id
            WODcursor = _db.query(DatabaseConstants.TBL_WORKOUTS, 
                                 new String[] { DatabaseConstants.WORKOUTS_ID, DatabaseConstants.WORKOUTS_NAME,
                                                DatabaseConstants.WORKOUTS_NOTES, DatabaseConstants.WORKOUTS_CFID }, 
                                 DatabaseConstants.WORKOUTS_ID + " = " + _wod_id, null, null, null, null);

            WODcursor.moveToFirst();
        }

        // Store WOD information into class instance variables and close cursor
        _wod_cfid = WODcursor.getInt(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_CFID));
        _wod_name = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NAME));
        _wod_notes = WODcursor.getString(WODcursor.getColumnIndex(DatabaseConstants.WORKOUTS_NOTES));
        WODcursor.close();

        // Return all exercises pertaining to this WOD
        _excCursor = _db.query(DatabaseConstants.TBL_EXERCISES, 
                              new String[] { DatabaseConstants.EXERCISES_ID, DatabaseConstants.EXERCISES_EXERCISE,
                                             DatabaseConstants.EXERCISES_REPS, DatabaseConstants.EXERCISES_NOTES }, 
                              DatabaseConstants.EXERCISES_WOD_ID + " = " + _wod_id, null, null, null, 
                              DatabaseConstants.EXERCISES_ID + " ASC");
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        _adapter.changeCursor(_excCursor);
        _adapter.notifyDataSetChanged();
        _WODlist.setOnItemClickListener(new WODlistClickListener());
    }

}

And the code in my onCreate that calls the task (when the activity is first loaded):

upAdapter = new updateAdapter().execute();

And in the button onClickListener:

            // Reset wod_id
            _wod_id = -1;

            // Update the underlying SimpleCursorAdapter
            upAdapter = new updateAdapter().execute();

Stacktrace of one of the AsyncTask (it's the same for all of them):

Object.wait(long, int) line: not available [native method]  
Thread.parkFor(long) line: 1535 
LangAccessImpl.parkFor(long) line: 48   
Unsafe.park(boolean, long) line: 317    
LockSupport.park() line: 131    
AbstractQueuedSynchronizer$ConditionObject.await() line: 1996   
LinkedBlockingQueue.take() line: 359    
ThreadPoolExecutor.getTask() line: 1001 
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1061  
ThreadPoolExecutor$Worker.run() line: 561   
Thread.run() line: 1096 

解决方案

AsyncTask under the hood uses a ThreadPoolExecutor. Those threads might not go away for a bit because it'd be a waste to keep creating and tearing down those threads too often. After a while if you create more AsyncTasks you'll find that it'll stop creating new threads and it'll re-use the old ones.

Update to address some details:

You would think that if there are free threads in the pool, it wouldn't create new ones, but this isn't exactly true. The idea is that there's a certain number of threads that are useful to have around to keep processing asynchronous tasks. This is called the core pool size. In Android's AsyncTask case, they seem to have set it to 5. If you look at the documentation for ThreadPoolExecutor it says:

When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.

There's also a maximum fittingly called the maximum pool size.

这篇关于AsyncTask的一直等待?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆