2011-07-27 17 views
5

Tuve un problema con el bloqueo de un hilo por alguna razón aún desconocida en mi aplicación de Android cuando intentaba matar el hilo B del hilo A (por lo general, a veces funcionaba). Supuse que era porque algunos de mis métodos realizaban llamadas a través de los hilos sin estar sincronizados. Hice el método de cancelar y muchos métodos que esencialmente eran controladores de eventos sincronizados e hizo que algunas variables compartidas fueran volátiles y todo funcionó.¿Intercambiar con el método de declaración sincronizado en java?

No sé cuál de las 20 extrañas declaraciones volátiles/sincronizadas que agregué realmente resolvió el problema, y ​​eso me hizo pensar: "¿Debería importarme? ¡Funciona, no te metas con eso!"

Por lo tanto, mi pregunta es: ¿Hay alguna compensación asociada con la declaración de un método sincronizado o una primitiva volátil? ¿Hay alguna razón para evitar estas declaraciones si no son necesarias?

Editar
El hilo (s) en cuestión es una conexión Bluetooth que está recibiendo/enviando los datos de streaming, por lo AsyncTask y otras soluciones de tipo subproceso de trabajo no funcionan bien. Están diseñados para realizar una tarea finita y terminar cuando esté terminado. Algunos, como ASyncTask, también agregan muchos sobrecargas que simplemente matan la aplicación. Para ejecutar continuamente hilos como este, utilizar un hilo sigue siendo la mejor manera de hacerlo.

Estoy usando un android Service para generar y administrar los hilos, así que estoy siguiendo los paradigmas de diseño de Android a ese respecto.

+0

Hay una (pequeña) penalización de rendimiento inherente. Es difícil decir cuál fue el "problema con el bloqueo de un hilo" (sondear un campo de miembro no volátil?), Pero agregar libremente sonidos "sincronizados" es una buena manera de lograr un punto muerto, y cómo sabes que tu aplicación es libre de condiciones de carrera?El gran problema es que tiene un * lote * de estado compartido entre subprocesos: necesita decidir qué se debe compartir, asegurarse de que el estado compartido sea seguro para subprocesos (haciendo que la mayor cantidad de ayuda posible sea inmutable) y decidir cómo se comunican los subprocesos. (¿Handler/ConcurrentLinkedQueue/LinkedBlockingQueue?). –

Respuesta

-1

Si funciona, no lo arregles por ahora :), pero para el próximo proyecto debes considerar usar AsyncTask. Dev Guide. No creo que el impacto en el rendimiento no sea una preocupación real en el contexto de Android, pero la complejidad, la legibilidad y el mantenimiento futuro pueden ser un problema (cancelar/eliminar el hilo, muchas variables compartidas).

+0

Conozco ASyncTask, pero esta es una aplicación de comunicación Bluetooth que requiere un hilo que se ejecuta constantemente. ASyncTask está pensado para una única tarea que finalizará en un tiempo finito en el futuro, no una conexión estable. ASyncTask es genial, pero no es una bala mágica. – CodeFusionMobile

+0

Lo siento, no sabía en dónde lo usa, pero basado en '20 impar volátil/sincronizado' sigue siendo bastante complejo para un programa Java. – user802421

+2

Para las comunicaciones Bluetooth de fondo, ¿no deberías hacerlo como un servicio continuo? Permita que el sistema Android administre el hilo de su servicio y haga que su aplicación hable con el servicio. – fluffy

4

En mi experiencia, generalmente es más fácil y a menudo más eficiente hacer su bloqueo en un nivel tan fino como sea posible, utilizando objetos sincronizados {...} para acceder a un objeto en particular. Además, si hay varios bloqueos que debe adquirir al mismo tiempo, SIEMPRE asegúrese de que siempre los esté adquiriendo en el mismo orden.

Los métodos estáticos tienen su propio pedazo de rareza del que preocuparse; un método de instancia sincronizada solo se sincronizará con esa instancia, no con la clase como un todo, por lo que si necesita sincronizar ambos en un método de instancia, deberá hacer algo como synchronized (this.class) {.. .} también, aunque si está aplicando lo anterior, realmente estaría haciendo synchronized() sobre los campos estáticos a los que está accediendo en el método particular.

Como otra nota, en general no desea generar sus propios hilos, y en su lugar debe usar los mecanismos preexistentes del sistema para la gestión de subprocesos (como ThreadPoolExecutor para colas de trabajo continuas o AsyncTask para actualizaciones de UI asincrónicas) . ThreadPoolExecutor tiende a ser más eficiente (y puede aprovechar mejor los dispositivos multi-core), pero tienes que hacer un trabajo extra si va a hacer cosas en la interfaz de usuario; AsyncTask, por otro lado, tiende a ser un poco más lento y pesado, pero también se ejecuta en la devolución de llamada PostExecute en el hilo de la interfaz de usuario.

+0

Todos estos métodos (ThreadPool, ASyncTask, etc.) están diseñados para ejecutar una tarea o alguna forma de procesamiento pesado que terminará cuando se termine el trabajo. Estoy administrando una conexión bluetooth activa y enviando docenas de paquetes de datos diferentes y monitoreando muchos estados y variables de conexión. Para un proceso no final como este, ASyncTask y los subprocesos de trabajo no son la elección correcta. – CodeFusionMobile

+0

Bien. Mi tercer párrafo era más una regla general y no específica para su pregunta tal como fue editada, pero todavía es algo a tener en cuenta en general. – fluffy

Cuestiones relacionadas