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:
- Android: Error al cargar la imagen en diferentes versiones de Android
- START_STICKY, el servicio Android de primer plano desaparece sin previo aviso
- La mejor manera de cargar datos externos en android
- Llamar al servicio web WSDL mediante el uso de retrofit android
- El host de destino no debe ser nulo o configurado en parameters.scheme = null, host = null
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> . .
- Envío de un mensaje sencillo de Servicio a Actividad
- Excepción con servicio web (java.net.SocketException Permiso denegado) en Android
- Error en Callin Java webservice de Android usando k-Soap
- Cómo convertir HttpEntity en JSON?
- No puedo conectarme a mi servicio web
- Android cómo enviar int y doble como namevaluepair como http post
- Cómo saber cuándo finaliza una llamada de Retrofit
- Cómo tratar un objeto JSON grande en Android
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.