ScheduledExecuterService.scheduleAtFixedRate crea varios grupos de hilos – Android
Tengo un AsyncTask
llamado UploadManager
en mi aplicación de Android, que comprueba los elementos procesados y los carga en el servidor.
Para este propósito estoy usando el ScheduledExecutorService.scheduleAtFixedRate
para comprobar artículos después de cada 1 minuto, y subirlos al servidor.
Sin embargo, a veces, hay múltiples grupos de hilos creados (esto sucede como el 10% de las veces), debido a que a veces la misma solicitud se envía dos veces al servidor, aunque esta concurrencia se maneja a nivel de servidor y cliente , Pero todavía no quiero que esto suceda en el lado del cliente.
A continuación se muestra cómo se ve el código.
En MainActivity (inicio-actividad), inicie el UploadManager como:
public class MainActivity extends BaseActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); . . . new UploadManager().execute(this); } }
UploadManager
funciona de la siguiente manera:
- Envío de un mensaje sencillo de Servicio a Actividad
- Android cómo enviar int y doble como namevaluepair como http post
- ¿Cómo puedo encontrar la cantidad de datos que se transfieren cuando hago una llamada de servicio web desde mi aplicación android?
- ¿Cuáles son las mejores prácticas para diseñar servicios web para aplicaciones móviles (en particular Android)?
- Conexión a un servicio web desde android - AsyncTask o Service?
public class UploadManager extends AsyncTask<Context, Integer, Integer> { private ScheduledExecutorService scheduledExecutorService; private static final int NUM_OF_THREADS = 5; private static final int DELAY_IN_SECONDS = 60; private Context context; private final Logger logger = new Logger(getClass().getSimpleName()); protected Integer doInBackground(Context... context) { this.context = context[0]; scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS); scheduledExecutorService.scheduleAtFixedRate(postInformation, 5, DELAY_IN_SECONDS, TimeUnit.SECONDS); return 0; } private Runnable postInformation = new Runnable() { @Override public void run() { if (NetworkManager.isInternetAvailable(context)) { uploadAcknowledgement(); } } }; private void uploadAcknowledgement() { List<Acknowledgement> ackList = null; try { logger.info("RUNNING TASK TO POST ACKNOWLEDGEMENT"); . . } } }
Cuando revisé los registros, dice:
35119 [pool-2-thread-1] INFO Upload Manager - [1363841355530] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT 35122 [pool-3-thread-1] INFO Upload Manager - [1363841355532] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT
Lo que indica claramente que hay múltiples grupos de hilos ahora, debido a que, uploadAcknowledgement()
método se llama varias veces.
La actividad MainActivity se declara en AndroidManifest.xml como:
<application android:label="@string/app_name" android:icon="@drawable/icon"> <activity android:name="MainActivity" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </activity> . .
- StartForeground () no muestra mi notificación
- Notificar a un servicio de Android cuando un cliente vinculado se desconecta
- ¿Cuándo usar un Servicio o AsyncTask o Handler?
- Retofit2 error java.io.EOFException: Fin de la entrada en la línea 1 columna 1
- Cómo obtener actividad en el servicio de intención
- ¿Cuál es la mejor práctica para compartir modelos entre un servidor API WEB y una aplicación cliente Android?
- ¿Cómo llamar a un servicio web .NET desde android?
- START_STICKY, el servicio Android de primer plano desaparece sin previo aviso
Finalmente descubrí las razones, si el servicio del postInformation()
ScheduledExecutor
se superpone, entonces genera nuevos hilos de trabajo (por ejemplo, en este caso, postInformation()
crea un nuevo hilo de trabajo) y eventualmente, un nuevo grupo.
Sin embargo, varios trabajadores pueden evitarse utilizando newSingleThreadScheduledExecutor en lugar de newScheduledThreadPool(int corePoolSize)'
.
Por lo tanto, en lugar de inicializar `scheduledExecutorService 'como:
scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS);
Debería haber sido inicializado como:
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
De esta manera, se garantizará que no hay varios subprocesos de trabajo en ejecución.
Usted tiene una lista de N número de archivos y comenzó X número de hilos para cargarlo sin especificar qué hilo para elegir qué archivo. Un enfoque para resolver esto para agregar los archivos que se cargarán en una cola de bloqueo y dejar que los hilos elegir los archivos que se cargarán de la cola. De esta manera ningún archivo será escogido dos veces.