【问题标题】:Default AsyncTask thread priority (BACKGROUND) is not applied不应用默认 AsyncTask 线程优先级 (BACKGROUND)
【发布时间】:2020-02-10 21:12:10
【问题描述】:

在默认的异步任务构造函数源中,我们有以下代码,它将线程优先级设置为Process.THREAD_PRIORITY_BACKGROUND = 10

  mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                postResult(result);
            }
            return result;
        }
    };

我创建了一个示例应用程序,在其中创建了简单的 asynctask,并在 doInBackground() 中通过

记录线程优先级

Log.d("@@@ AsyncTask", "Thread name = " + Thread.currentThread().getName() + "Tread priority " + Thread.currentThread().getPriority());

预期结果: com.example.myapplication D/@@@ AsyncTask: Thread name = AsyncTask #1Tread priority 10

实际结果: com.example.myapplication D/@@@ AsyncTask: Thread name = AsyncTask #1Tread priority 5

后台线程的线程优先级与主线程优先级相同 com.example.myapplication D/@@@ MainActivity onCreate: Thread name = mainTread priority 5

我已经在 API 19 和 API 26 上对此进行了测试。结果是一样的。

为什么异步任务中没有应用后台线程优先级? 还是我阅读优先级的方法不对?

我可以将资源上传到 github,但上传的内容不多。只有 AsyncTask 和 log 语句。

【问题讨论】:

    标签: android multithreading android-asynctask thread-priority


    【解决方案1】:

    来自Process.setThreadPriority的javadoc:

    设置调用线程的优先级

    AsyncTask.execute() 方法在默认的Executor 中执行AsyncTask.doInBackground()Executor 管理线程池并允许您将任务提交到其中一个线程。为Executor 创建线程的类是ThreadFactory。您需要在Executor 上执行ThreadFactory,以创建具有所需优先级的线程。

    class PriorityThreadFactory(
      namePrefix: String,
      private val threadPriority: Int = Thread.NORM_PRIORITY
    ) : ThreadFactory {
    
      private val group: ThreadGroup = System.getSecurityManager()?.threadGroup ?: Thread.currentThread().threadGroup
      private val threadNumber = AtomicInteger(1)
      private val namePrefix: String = "pool-$namePrefix-thread-"
    
      override fun newThread(r: Runnable): Thread {
        val t = Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0)
        if (t.isDaemon) {
          t.isDaemon = false
        }
        if (t.priority != threadPriority) {
          t.priority = threadPriority
        }
        return t
      }
    }
    

    因此,当您执行 AsyncTask 时,您将传递使用 PriorityThreadFactoryExecutor

      val executor = Executors.newSingleThreadExecutor(PriorityThreadFactory("asynctask", Process.THREAD_PRIORITY_BACKGROUND)
      asyncTask.executeOnExecutor(executor)
    

    【讨论】:

    • 谢谢,但为什么默认执行程序,运行此代码时 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);结果 = doInBackground(mParams);不改变它的线程优先级?或者一旦线程被创建,我们就不能改变线程优先级?什么原因,这种情况下这段代码在 AsyncTask 构造函数中?
    • AFAIK,后台线程组的默认优先级为Process.THREAD_PRIORITY_BACKGROUND。默认的AsyncTaskExecutor是一个静态单例,它的线程属于一个不允许程序员改变线程优先级的线程组。当您在 ThreadFactory 中创建新的 Thread 时,您是在允许这样做的线程组中执行此操作的。
    【解决方案2】:

    原来我获取线程优先级的方法是错误的。

    获取线程优先级的正确方法是Process.getThreadPriority(Process.myTid())

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 2012-11-17
      相关资源
      最近更新 更多