Приоритет потока AsyncTask по умолчанию (BACKGROUND) не применяется - PullRequest
0 голосов
/ 14 октября 2019

В исходном конструкторе асинхронных задач по умолчанию у нас есть следующий код, который устанавливает приоритет потока на 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;
        }
    };

Я создал пример приложения, в котором я создал простую асинхронную задачу, и в 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 и лог-оператор.

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Оказалось, что мой метод получения приоритета потока был неправильным.

Правильный подход для получения приоритета потока - Process.getThreadPriority(Process.myTid())

0 голосов
/ 14 октября 2019

Из javadoc для Process.setThreadPriority:

Установить приоритет вызывающего потока

Метод AsyncTask.execute() выполняет AsyncTask.doInBackground() по умолчанию Executor. 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, вы передаете Executor, который используетPriorityThreadFactory.

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