【问题标题】:Java ScheduledExecutorService executes only onceJava ScheduledExecutorService 只执行一次
【发布时间】:2017-05-24 12:54:10
【问题描述】:

我是 Java 新手,正在尝试制作一个 Android APP,它会定期从我的 Ubidots 变量中读取一些信息。

经过一些在线研究,我设法找到了这种方法..

问题是它只执行一次。在第一次迭代之后,它再也不会通过 syncTimer。

        Runnable syncTimer = new Runnable() {
        public void run() {
            ubi.execute(0);

            if (!syncComplete)
            {
                System.out.println("Sync not completed. We'll wait");

                while (!syncComplete)
                {
                    //wait.
                }
            }

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try
                    {
                        syncComplete(tempValue, g_tempVal.toString());
                    }
                    catch (Exception e)
                    {
                        System.err.println("error in executing. It will no longer be run!");
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }

                }
            });

        }
    };

    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    executor.scheduleAtFixedRate(syncTimer, 0, 2, TimeUnit.SECONDS);

这是我的代码,对这个问题有帮助吗?我完全不知道在谷歌上搜索什么以找到解决方法。

我从未使用过 Java/Android 编程,只使用过其他语言。

syncComplete 是连接到 Ubidots 并检索变量的 AsyncTask 之后的布尔集。

   public class ApiUbidots extends AsyncTask<Integer, Void, Void> {
    private final String API_KEY = "key";
    private final String VARIABLE_ID = "var";

    @Override
    protected Void doInBackground(Integer... params) {
        ApiClient apiClient = new ApiClient(API_KEY);
        Variable temperature = apiClient.getVariable(VARIABLE_ID);
        if (params[0] == 0)
        {
            g_tempVal = temperature.getValues()[0].getValue();
            syncComplete = true;
        }
        if (params[0] == 1)
        {
            //implement write function
        }

        return null;
    }

}

【问题讨论】:

  • 你的 while 永远运行。由于您阻止了该线程,因此该线程甚至无法重用。
  • 不,它没有,我在描述中说过,一旦收到来自 Ubidots 的数据,我就会将其设置为 true ......我已经检查过了,这不是这里的问题。

标签: java android timer concurrency scheduling


【解决方案1】:

如果syncComplete 的更改是由另一个线程进行的,则您的线程将看不到这些更改。您需要将 syncComplete 变量声明为 volatile,如下所示:

public volatile boolean syncComplete=false;

使用 volatile 变量可降低内存一致性错误的风险,因为对 volatile 变量的任何写入都会与后续读取该相同变量建立起先发生关系。这意味着对 volatile 变量的更改始终对其他线程可见。

https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

此外,通过在 while 循环中旋转来主动等待是不好的做法。请尝试锁定。

【讨论】:

  • 我会研究一下锁定,看看我是否能理解如何使用它。同时......这并没有解决它。问题不在于 syncComplete 变量,它甚至在 2 秒等待时间后都没有开始第二次迭代。在执行第一个之后它只是......什么都不做,它不会卡在那个while循环中。
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 2016-11-10
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 2014-02-27
  • 2021-10-16
  • 1970-01-01
相关资源
最近更新 更多