Подтвердить что ты не робот

Тема, зацикленная на BlockingQueue.take без видимых причин

Я наткнулся на действительно странную проблему, и я не могу ничего понять. Сначала немного предыстории:

Я пытаюсь запустить JavaScriptCore и использовать его как язык сценариев для Android-приложения. Проблема в том, что размер стека в основном потоке довольно ограничен для старых версий Android (что-то вроде 12k на API 16). Тем не менее, я все равно хотел бы позвонить в JS по основному потоку, попросить его запросить вещи и все это синхронно. Нет проблем - я выпью пару каналов... khm... SynchronousQueues и отскакивает выполнение взад и вперед. Вот как выглядит мой код.

Это довольно просто - каждый раз, когда что-то вызывает отсрочку, он отскакивает от другого потока и продолжает оттуда. Единственная проблема - это не работает. В реальном использовании с выполнением Javascript-кода он в какой-то момент не работает довольно надежно, хотя и не в том же месте для эмулятора и разных устройств. Logcat всегда выглядит довольно безобидным:

I/JavaScriptCore: Lockstep [Main]: Defer
I/JavaScriptCore: Lockstep [Main]: Send EXECUTE_FUNC
I/JavaScriptCore: Lockstep [Background]: Receive EXECUTE_FUNC
I/JavaScriptCore: Lockstep [Background]: Defer
I/JavaScriptCore: Lockstep [Background]: Send EXECUTE_FUNC

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

На одном из моих устройств я мог бы установить условную точку останова для точного момента, когда это перестанет работать, и я могу приостановить ее, так как MAIN ожидает сообщения EXECUTE. Сообщение не пустое, foregroundQueue в этой точке работает, я могу опросить его с или без тайм-аута из Android Studio, взять его размер, что угодно. Как только я перехожу, все операции зависают.

Конечно, я подозревал JNI shenanigans, но в Logcat нет дампов памяти, ошибок сегментации или каких-либо предупреждений.

Кроме того, это не просто взять - даже если я делаю это с действительно грязным занятым ожиданием:

Message msg = incoming.poll();
if(msg == null) {
 Thread.sleep(20);
 continue;
}

Main застрял в опросе, фоновый поток продолжает весело отрываться в другой очереди каждые 20 миллисекунд.

Я попробовал развёртывание отладки с действительно ленивым факториалом, который любит много спать, и у него нет проблем, несмотря на то, что он имеет 200 глубоких, целых переполнений:

LockstepThread t = new LockstepThread();

int deferredFactoriel(final int n) {
  if(n == 0) {
    return 1;
  }
  return n * t.defer(new Functor<Integer>() {
    @Override
     public Integer call() {
       try {
         Thread.sleep(20);
       } catch (InterruptedException e) {
         e.printStackTrace();
       }
       return deferredFactoriel(n-1);
    }
  });
}

@Override
public void onCreate() {

  super.onCreate();

  for(int i=0; i<200; ++i) {
    Log.i("Test", i+"! = " + deferredFactoriel(i));
  }

...

Что, наверное, самое странное, заключается в том, что не имеет значения, какую синхронизацию я использую. SynchronizedQueue, ArrayBlockingQueue, LinkedBlocking queue - он всегда терпит неудачу в одном и том же месте с тем же самым дампом потока. Черт, я даже сделал свой собственный обменник, чтобы увидеть, что я не схожу с ума, и он все равно застрял в том же ключе.

Так что да, я полностью в тупике. Есть идеи, что происходит? Любая помощь с отладкой будет очень оценена.

4b9b3361

Ответ 1

почему вы используете поток. Также есть альтернативы для потока. Попробуй используйте это: возможно, это его работы

static Timer timer;
    private TimerTask timerTask;


try {
                timer = new Timer();
                    timerTask = new TimerTask() {

                        @Override
                        public void run() {
                        }
                        }
                    };
                    timer.schedule(timerTask, 4000);
                } else {
                     timer.cancel();
                    // timer.purge();
                    MainHomeActivity.appendLogSocket("UPDATE RECEIVER : ",
                            "TIMER STOPED");

                }
            } catch (Exception e) {
Log.e(      "Socket update receiever error: ", e.toString());

            }