2017-05-24 38 views
0

私はJavaを初めて使い、定期的に私のUbidots変数からいくつかの情報を読み込むAndroidのAPPを作ろうとしています。Java ScheduledExecutorServiceは一度だけ実行されます

問題は、それが一度だけ実行されるということです私はそれをやって、この方法を見つけるために管理し、オンラインでいくつかの研究の後..

。最初の反復後、再び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; 
    } 

} 
+0

あなたは永遠に実行されます。あなたがそれをブロックしてから、スレッドは再利用することさえできません。 – Nathan

+0

いいえ、私は説明では、Ubidotsのデータが受信されたら、私はそれを真に設定していると言いました...私はそれを確認しました、ここでは問題ではありません。 –

答えて

0

syncCompleteへの変更は、別のスレッドが行った場合は表示されません。あなたはこのように、揮発性としてあなたsyncComplete変数を宣言する必要があります:volatile変数への書き込みが、後続との事前発生関係を確立しているため

public volatile boolean syncComplete=false;

volatile変数を使用すると、メモリの整合性エラーのリスクを低減しますその同じ変数の読み込み。これは、揮発性変数への変更が他のスレッドから常に見えることを意味します。

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

また、whileループでスピンすることにより、アクティブな待機は悪い習慣です。代わりにロックを試みてください。

+0

ロックについて少し調べて、使用方法を理解できるかどうか確認します。その間に...これはそれを修正しませんでした。問題はsyncComplete変数ではなく、2秒の待機時間後に2回目の繰り返しを開始することさえありません。最初のものを実行した後は、ただ何もしません。ループ中に固執しません。 –

関連する問題