Emisión de concurrencia para la cancelación del bucle de encuesta larga
Tengo un problema que espero resolveré escribiendo esta pregunta pero si no voy a publicar y ver si alguien puede ayudar.
Estoy utilizando una biblioteca de cliente (que está mal escrito me siento) para interactuar con un servidor de chat en tiempo real que utiliza el estilo de COMET largo de sondeo a través de HTTP. Tengo problemas con la cancelación de la encuesta larga en ciertas situaciones y sospecho que puede que tenga que añadir algún código de manejo de concurrencia, pero estoy encontrando difícil encontrar la mejor manera de hacer esto por las siguientes razones.
- Android Syncadapter no permitir que el usuario elija sincronizar o no sincronizar
- SyncAdapter siempre en estado pendiente
- ¿Cómo actualizar la empresa de contacto de Android?
- Sincronización de contactos en mi aplicación
- ¿Cómo mantener sincronizados los datos de una aplicación de Android en varios dispositivos?
El código de suscripción (que inits el sondeo largo) se implementa como un bucle grande con el siguiente
doLongPoll() { while(true) } //IF channel field boolean unsubscribe == TRUE, if so BREAK; //perform GET request (and store channel HTTPClient used for this call) //remove HTTPClient used for this call //IF channel field boolean unsubscribe == true, if so BREAK; //IF connection problem sleep(1500) then CONTINUE //post received data to listeners } }
La llamada unsubscribe (que llamará a otro hilo)
unsubscribe() { //set channel field boolean unsubscribe == FALSE //get channel HTTPClient and shutdown }
He aislado el caso del problema donde las operaciones son entrelazado. A mí esto parece un resultado del código que es multi-hilo y el código del cliente que no es hilo seguro. También mala gestión y no reutilización del httpClient
no está ayudando.
Uno de los problemas que tengo es por debajo de donde la llamada unsubscribe no detiene la próxima getRequest de tener lugar.
THREAD 1 (polling) THREAD 2 -------- -------- do unsubscribe check (pass) unsubscribe called set unsubscribe = true check if httpClient saved (none) perform getRequest (save HttpClient first)
Me gustaría saber lo que la gente piensa que el mejor enfoque para este problema sería (el tiempo también es limitado por lo que no puedo reescribir demasiado del código!)
Para solucionar esto, pensé que podría utilizar un bloque de sincronización de la primera httpClient
la suscripción comprobar en el hilo 1 hasta el punto de la httpClient
se guarda justo antes de la solicitud de obtener real se realiza y sincronizar el método unsubscribe utilizando el mismo bloqueo. Esto no es práctico en este momento ya que el primer bloque de sincronización mencionado comenzaría en una llamada de método y terminaría más abajo en la cadena de llamada de método (debido a cómo se escribe la lib), lo que se siente muy mal, por lo que se necesitaría alguna refactorización.
O podría crear un único httpClient
por canal en lugar de por solicitud y, a continuación, siempre podría ser apagado y podría potencialmente ignorar la sincronización (creo).
O como se sugiere a continuación, podría utilizar interrupciones para el mismo propósito
Cualquier sugerencia sería bienvenida – voy a editar si tengo algún progreso!
Gracias
- Cómo agregar programaticamente una cuenta personalizada en android?
- SQLite en Android y MongoDB con sincronización
- En Android, ¿debe ejecutarse un adaptador de sincronización de contactos en un proceso independiente?
- ¿Cómo configurar correctamente el syncAdapter?
- Patrón de diseño recomendado para escribir en la base de datos SQLite en Android
- ¿Cómo usar Git en Android?
- Recursos del adaptador de sincronización de Android
- Monitor de estado de subprocesos. ¿Cómo depurar esto? ¿Qué lo causa?
Compré Java Concurrency en la práctica como resultado de este problema y encontró que discutir un tema muy similar a éste en el Capítulo 7: Cancelación y cierre que puede resumirse por la cita
La interrupción suele ser la forma más exitosa de implementar la cancelación
Como el HttpClient está bloqueando socket IO que no soporta interrupción así que tengo un enfoque de dos puntas. httpClient
mi httpClient
, compruebo para la interrupción apenas antes de la httpClient.execute()
real de httpClient.execute()
y en mi método del unsubscribe()
interrumpo el hilo y entonces llamo httpClient.getConnectionManager().shutdown();
. Esto parece cuidar de mi problema y fue un cambio muy simple. No más problemas de intercalación!
También establecí el campo booleano de anular unsubscribe
a volatile
como se sugirió lo que debería haber hecho antes – esto por sí solo sin embargo no habría resuelto el problema
1) Establecer unsubscribe como volátil
2) Para mayor seguridad, proteja el acceso (lectura / escritura) para cancelar la suscripción con, por ejemplo, un Semáforo
- Cómo obtener clics en RecyclerView (NO los niños)
- ¿Cómo evitar que algunos usuarios actualicen la aplicación del mercado de Android?