Java ScheduledExecutorService 只执行一次
Java ScheduledExecutorService executes only once
我是 Java 的新手,正在尝试制作一个 Android 应用程序,定期从我的 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);
这是我的代码,对这个问题有什么帮助吗?我完全不知道要在 google 上搜索什么来找到解决它的方法。
我从来没有用 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;
}
}
如果其他线程对 syncComplete
所做的更改对您的线程不可见。您需要将 syncComplete
变量声明为易变的,如下所示:
public volatile boolean syncComplete=false;
Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads.
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
此外,通过在 while 循环中旋转来主动等待是不好的做法。尝试锁定。
我是 Java 的新手,正在尝试制作一个 Android 应用程序,定期从我的 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);
这是我的代码,对这个问题有什么帮助吗?我完全不知道要在 google 上搜索什么来找到解决它的方法。
我从来没有用 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;
}
}
如果其他线程对 syncComplete
所做的更改对您的线程不可见。您需要将 syncComplete
变量声明为易变的,如下所示:
public volatile boolean syncComplete=false;
Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads.
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
此外,通过在 while 循环中旋转来主动等待是不好的做法。尝试锁定。