线程卡在阻塞队列上.采取没有明显原因

2022-09-03 03:04:31

我偶然发现了一个非常奇怪的问题,我无法理解任何事情。先来一点背景故事:

我正在尝试运行JavaScriptCore,并将其用作Android应用程序的脚本语言。麻烦的是,主线程上的堆栈大小在较旧的Android版本上非常有限(在API 16上大约为12k)。但是,我仍然想在主线程上调用JS,让它回调以请求内容,并使所有这些内容看起来都是同步的。没问题 - 我会鞭打几个香奈...嗯......同步排队并来回反弹执行。这是我的代码的样子。

这很简单 - 每次调用延迟时 - 它都会反弹到另一个线程并从那里继续。唯一的问题是,嗯,它不起作用。在执行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 则停放在 incoming.take 上。没有其他线程与此交互。

在我的一台设备上,我可以为它停止工作的确切时刻设置一个条件断点,并且可以在MAIN等待该EXPERACT消息时暂停它。该消息是非空的,此时的前景队列正在工作,我可以在有或没有Android Studio超时的情况下轮询它,取其大小,无论什么。一旦我跨过,所有的操作都会挂起。

当然,我怀疑JNI的恶作剧,但是在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));
  }

...

最奇怪的可能是,我使用什么同步并不重要。SyncedQueue,ArrayBlockingQueue,LinkedBlocking queue - 它总是在同一个位置失败,线程转储完全相同。地狱,我甚至制作了自己的交换器,只是为了看到我不会发疯,它仍然以同样的方式卡住。

所以,是的,我完全被难住了。有什么想法是怎么回事?任何调试此内容的帮助将不胜感激。


答案 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());

            }

答案 2

推荐