Пользовательская реализация Runnable, которая проверяет Thread.currentThread (). IsInterrupted () между каждой строкой кода

Я пытаюсь реализовать класс, который может управлять входящими Runnables и отменять любые Runnables, независимо от того, где они находятся в своем коде, гарантированно.

Например, в Android я бы хотел сделать следующее.

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    manager.submit(new Runnable() {
        @Override
        public void run() {
            someLongRunningTaskThatCallsTheUi();
        }
    });
}

@Override
public void onPause() {
    manager.cancel(); // cancels all Runnables to avoid issues with calling the UI
}

Как я могу подойти к этой проблеме, если метод Future cancel() на самом деле не гарантирует отмены исполняемого кода, а shutdownNow() ExecutorService имеет ту же проблему?

Из того, что я вижу, мне нужно было бы добавить проверку на наличие Thread.currentThread().isInterrupted() перед каждым фрагментом кода пользовательского интерфейса, который я хочу вызвать и выйти из метода, чтобы каким-то образом избежать дальнейших вызовов.

Вы, мощь, сможете сделать это с помощью какой-либо прямой манипуляции с байтовым кодом или переплетения кода. Если оставить в стороне эти темные искусства, вы просите не о том, как работают нити.

StackOverthrow 06.04.2018 22:34

Я был под таким впечатлением, когда столкнулся с проблемой. Тогда есть ли лучший способ прийти к этому? Я хочу запустить длительную операцию в фоновом режиме одним нажатием кнопки, но также разрешить пользователю отступить, если он хочет, отменив операцию.

jeffmcnd 08.04.2018 02:46

Вы сами пишете эти Runnables или это плагины сторонних производителей для вашего приложения?

StackOverthrow 09.04.2018 17:59

Я их пишу. Я просто не хочу помещать if (isInterrupted) return; в несколько мест исполняемого файла. Кажется, это довольно хрупкий способ писать код.

jeffmcnd 10.04.2018 19:31

Есть ли причина, по которой AsyncTask не работает? Его отмена не остановит фоновую работу, которая не проверяет статус, но гарантирует, что в потоке пользовательского интерфейса больше не произойдет обратных вызовов. Для процессов с несколькими шагами выполнение одной задачи может запускать следующую.

StackOverthrow 10.04.2018 20:04

Думаю, я понимаю вашу точку зрения. Я попытаюсь взглянуть на это под другим углом. Обычно я избегаю AsyncTasks, потому что у меня были проблемы с ними в прошлом (например, в далеком прошлом), поэтому, возможно, пришло время вернуться к ним. Спасибо за помощь!

jeffmcnd 11.04.2018 21:55
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
52
1

Ответы 1

Рассмотрите возможность использования AsyncTask. Отмена AsyncTask не гарантирует, что фоновая работа остановится, если задача не проверит свой собственный статус. Но отмена действительно гарантирует, что onProgressUpdate и onPostExecute не будут вызваны. Если onProgressUpdate не подходит для обновления пользовательского интерфейса между шагами, поместите каждый шаг в отдельную задачу.

Несколько советов для AsyncTask:

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

Остерегайтесь ссылок на действия. Плохое предложение (популяризированное известной книгой IIRC) гласит, что нужно присвоить задаче WeakReference деятельности и проверить ее перед доступом к пользовательскому интерфейсу. Это неверно, потому что структура может содержать ссылку на действие после вызова onDestroy, и когда он очищает свою ссылку, WeakReference не станет нулевым, пока GC не заметит, что действие не является полностью доступным. Вы должны поддерживать коллекцию запущенных задач внутри своей операции и отменять их, когда действие приостановлено или уничтожено.

Чтобы задачи выполнялись при изменении конфигурации, разместите их в сохраненном фрагменте без заголовка.

Другие вопросы по теме