2017-05-24 5 views
0

Je suis nouveau sur Java et j'essaie de créer une application Android qui lit périodiquement certaines informations de ma variable Ubidots.Java ScheduledExecutorService s'exécute une seule fois

Après quelques recherches, je en ligne a réussi à trouver cette façon de le faire ..

Le problème est qu'il exécute une seule fois. Après la première itération, il ne passe plus jamais par 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); 

Ceci est mon code, de l'aide pour ce problème? Je suis à court d'idées quoi chercher sur google pour trouver un moyen de le résoudre.

Je n'ai jamais programmé en Java/Android, seulement utilisé d'autres langues. SyncComplete est un ensemble booléen après un AsyncTask qui se connecte à Ubidots et récupère des variables.

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

Votre temps s'écoule pour toujours. Le thread ne peut même pas être réutilisé depuis que vous l'avez bloqué. – Nathan

+0

non, je n'ai pas dit, dans la description, que je le mets à vrai une fois que les données d'Ubidots sont reçues ... J'ai vérifié cela, ce n'est pas le problème ici. –

Répondre

0

Les modifications à syncComplete ne sont pas visibles à votre fil si elles sont faites par un autre fil. Vous devez déclarer votre variable syncComplete comme volatile, comme ceci:

public volatile boolean syncComplete=false;

Utilisation des variables volatiles réduit le risque d'erreurs de cohérence de la mémoire, car toute écriture à une variable volatile établit une relation qui se passe-avant avec la suite lectures de cette même variable. Cela signifie que les modifications apportées à une variable volatile sont toujours visibles pour les autres threads.

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

Aussi, attente active en tournant dans une boucle while est une mauvaise pratique. Essayez de verrouiller à la place.

+0

Je vais faire quelques recherches sur le verrouillage et voir si je peux comprendre comment l'utiliser. Pendant ce temps ... ça n'a pas arrangé ça. le problème n'est pas avec la variable syncComplete, il ne démarre même pas la deuxième itération après le temps d'attente de 2 secondes. Après avoir exécuté le premier, il ne fait rien ... il ne reste pas bloqué dans cette boucle. –