Java 哨兵安卓安瑞,会不会有虚惊一场?

Java 哨兵安卓安瑞,会不会有虚惊一场?,java,android,sentry,Java,Android,Sentry,我正在使用Sentry Android 2.3.0 SDK收集Android崩溃和ANR,在过去的几个月里,出现了一些奇怪的ANR。所有这些都发生在用户在一段时间后打开设备时,所有这些都发生在MessageQueue.next方法中。在深入挖掘Sentry SDK源代码后,我发现在Android中处理ANR的核心逻辑在类中,IMHO可以简化如下: public class Test { BlockingQueue<Runnable> queue = new LinkedBlock

我正在使用Sentry Android 2.3.0 SDK收集Android崩溃和ANR,在过去的几个月里,出现了一些奇怪的ANR。所有这些都发生在用户在一段时间后打开设备时,所有这些都发生在
MessageQueue.next
方法中。在深入挖掘Sentry SDK源代码后,我发现在Android中处理ANR的核心逻辑在类中,IMHO可以简化如下:

public class Test {
  BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();

  class MainThread extends Thread {

    public void run() {
      while (!isInterrupted()) {
        Runnable r;
        try {
          r = queue.take();
        } catch (InterruptedException e) { return; }
        r.run();
      }
    }
  }

  class WorkerThread extends Thread {
    private AtomicLong tick = new AtomicLong(0);
    private AtomicBoolean reported = new AtomicBoolean(false);

    private final Runnable ticker = new Runnable() {
      public void run() {
        tick = new AtomicLong(0);
        reported.set(false);
      }
    };

    public void run() {
      while (!isInterrupted()) {
        boolean needPost = tick.get() == 0;
        tick.addAndGet(100L);
        if (needPost) {
          queue.add(ticker);
        }
        try {
          Thread.sleep(100L);
        } catch (InterruptedException e) {
          return;
        }

        if (tick.get() != 0 && !reported.get()) {
          // TODO: if ActivityManager available, further check
          reported.set(true);
          throw new RuntimeException("Bang!");
        }
      }
    }
  }
}
公共类测试{
BlockingQueue=新建LinkedBlockingQueue();
类MainThread扩展线程{
公开募捐{
而(!isInterrupted()){
可运行r;
试一试{
r=queue.take();
}catch(InterruptedException e){return;}
r、 run();
}
}
}
类WorkerThread扩展线程{
私有AtomicLong勾选=新的AtomicLong(0);
私有AtomicBoolean reported=新的AtomicBoolean(false);
私有最终可运行股票代码=新可运行(){
公开募捐{
勾号=新原子长(0);
已报告。设置(错误);
}
};
公开募捐{
而(!isInterrupted()){
布尔needPost=tick.get()=0;
勾选addAndGet(100L);
如有需要(needPost){
添加(股票代码);
}
试一试{
睡眠(100L);
}捕捉(中断异常e){
返回;
}
如果(勾选.get()!=0&&!报告的.get()){
//TODO:如果ActivityManager可用,请进一步检查
已报告。设置(真);
抛出新的RuntimeException(“砰!”);
}
}
}
}
}

我的问题是,tick变量不应该是易变的吗?此代码是否会导致可见性问题?如果是这样,此代码是否会导致生产代码中出现假警报?

afaik
AtomicLong
getter和setter从易失性字段读取/写入,因此不需要,我们对该算法进行了改进以避免误报/误报,请将SDK升级到最新版本


其中一个主要变化是:

谢谢你的回复,我担心的是,如果有一种情况是ActivityManager不可用,比如用户在很长一段时间后返回应用程序,并且(虽然它是对AtomicLong的引用,但我们没有在主线程中使用它的getter/setter)触发了可见性问题,我们可能会错过看门狗线程中的
needPost
条件,从而触发超时。如果超时为真,
tick
可能是
final
并执行
tick.set(0)而不是
tick=new AtomicLong(0)是否要提交PR?