Foro de elhacker.net

Programación => Java => Mensaje iniciado por: klaine en 14 Junio 2011, 23:43 pm



Título: [Threads] wait() y notify()
Publicado por: klaine en 14 Junio 2011, 23:43 pm
Buenas, me gustaria saber si existe alguna documentacion para seres humanos de como se usan los hilos en java xD, en teoria, se instancia un Thread y en el constructor se le pasa una nueva instancia de Runnable() sobreescribiendo el metodo run(), para iniciarlo se llama al metodo start(), suponiendo que el metodo run() ejecuta un bloque de codigo infinito (digamos un while(true) { ... } ) tendriamos un proceso llamado hilo que acompañaría a nuestro programa principal sin que este espere el return del metodo run(), ahora bien, si dentro de mi programa principal accedo al objeto que contiene el hilo y llamo al metodo suspend(); el metodo se detiene, si llamo a resume(); el hilo continua su ejecucion, mi gran duda es:

1) ¿Por que al llamar al Object.wait(); en vez de suspend(); no se produce la pausa, sino que espera alrededor de un segundo y continua?

y (Aunque es un poko obvio, sabiendo que no se produce la pausa)

2) ¿Por que al llamar al Object.notify(); me suelta IllegalMonitorStateException, siendo que anteriormente (supuestamente) se provocó una pausa en el hilo con wait();?


He buscado y he leído varias cosas pero lo uniko que consegui entender fue esto  :P, imaginate un mono tratando de descubir para que funciona una rueda, asi me siento xD.

De antemano, gracias  :D

Saludos  ;)

PD: dejo un ejemplo de lo que prové (la interface grafica la hice con un ide asi que la omitire)

Código
  1.  
  2. public class hilo{
  3.  
  4. volatile int c=0;
  5.  
  6. Thread t=null;
  7.  
  8. public hilo(){
  9.  
  10. init_hilo();
  11.  
  12. }
  13.  
  14. public void init_hilo(){
  15.  
  16. t=new Thread(new Runnable(){
  17.  
  18. public void run(){
  19.  
  20. while(true){
  21.  
  22. c++;
  23. System.out.println(c);
  24.  
  25. }
  26.  
  27. }
  28.  
  29. });
  30.  
  31. }
  32.  
  33. public static void main(String[] args){
  34.  
  35. new hilo();
  36.  
  37. try{
  38.  
  39. t.wait();
  40.  
  41. t.notify();
  42.  
  43. //si uso suspend(); y resume(); no me da problemas =/
  44.  
  45.  
  46. }
  47.  
  48. }
  49.  
  50. }
  51.  
  52.  


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 18 Junio 2011, 00:19 am
Yo recomendaría, si te interesa lo de ejecución de varios hilos en java, es que usases semáforos, o monitores, los métodos funcionan perfectamente y no es muy complicado entenderlo, si te interesa busca algo lee y pregunta.

Saludos y suerte!


Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 18 Junio 2011, 07:51 am
Los metodos wait() y notify() en verdad no me funkan como los estoi usando, por eso pregunto como hacerlo, entiendo que trates asi a gente que no lee pero he leido bastante y no entiendo nada, de verdad agradecere sus comentarios.

Saludos  ;)


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 18 Junio 2011, 13:26 pm
Te respondí eso porque yo en los programas que he tenido que hacer para la universidad de programación concurrente, hemos usado semáforos, monitores, y luego algunas técnicas de paso de mensajes que son algo más complicadas, pero que tampoco es mucho. Por eso te recomiendo usar semáforos:

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html

En ese enlace tienes la clase de java, no se que conocimientos tendrás, si habrás oido alguna vez el concepto de semáforo o si no quieres usar otra cosa que no sea los métodos que heredan todas las clases de Object wait() y notify(). Si te interesa esto de parar la ejecución de los hilos y reanudarlos mediante semáforos, comentamelo y te ayudo. Los monitores es otra opción, aquí tienes su descripción:

http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantLock.html

Si te interesan también puedo comentarte algunos aspectos que yo he visto (no soy un experto en la materia pero algo se xD).

Si quieres también podrías postear el código que no te funciona y podríamos mirarlo el resto.

Saludos y suerte!


Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 19 Junio 2011, 05:44 am
Genial, ya me dare un tiempo para revisar eso Xd, sabes hice un codigo donde me funka el wait() y notify() quiero preguntar dos cosas:

1) Si es la forma correcta de hacerlo

2) Como funkan los blokes synchronized (entendi que se usan para suspender y resumir como wait() y notify(), pero kizas sirve para algo que no entiendo o no me he percatado)

Conocimientos que tengo sobre java?, realmente no se mucho, pero me empeño en aprender =)

Desde ya gracias por las respuestas

Saludos  ;)

El code:

Clase main:

Código
  1. package testing;
  2.  
  3. //<editor-fold defaultstate="collapsed" desc="Clase Main">
  4. public class Main {
  5.  
  6.    volatile int c=0;
  7.  
  8.    //<editor-fold defaultstate="collapsed" desc="hilo (r)">
  9.    runnable r=new runnable(){
  10.  
  11.        @Override
  12.        public void run(){
  13.  
  14.            while(true){
  15.  
  16.                if(!running){
  17.  
  18.                    try{
  19.                      synchronized(this){
  20.                      wait();
  21.                        }
  22.                    }catch(InterruptedException ex){
  23.  
  24.                    }
  25.  
  26.                }
  27.  
  28.                use();
  29.  
  30.            }
  31.  
  32.        }
  33.  
  34.    };//</editor-fold>
  35.  
  36.    //<editor-fold defaultstate="collapsed" desc="Constructor">
  37.    public Main(){
  38.  
  39.        programa();
  40.  
  41.    }//</editor-fold>
  42.  
  43. //<editor-fold defaultstate="collapsed" desc="Manipulacion del hilo">    
  44.    public void programa(){
  45.  
  46.        r.start();
  47.  
  48.        r.running=!r.running;
  49.  
  50.        try{
  51.  
  52.        Thread.sleep(10000);
  53.  
  54.        }catch(InterruptedException ex){
  55.  
  56.        }
  57.  
  58.        r.running=!r.running;
  59.  
  60.        synchronized(r){
  61.  
  62.            r.notify();
  63.  
  64.        }
  65.  
  66.  
  67.        try{
  68.  
  69.        Thread.sleep(10000);
  70.  
  71.        }catch(InterruptedException ex){
  72.  
  73.        }
  74.  
  75.        r.running=!r.running;
  76.  
  77.    }//</editor-fold>
  78.  
  79.    //<editor-fold defaultstate="collapsed" desc="Metodo que el hilo usa">
  80.    public synchronized void use(){
  81.  
  82.        c++;
  83.        System.out.println(c);
  84.  
  85.    }//</editor-fold>
  86.  
  87.    //<editor-fold defaultstate="collapsed" desc="Metodo main">
  88.    public static void main(String[] args){
  89.  
  90.        new Main();
  91.  
  92.    }//</editor-fold>
  93.  
  94. }
  95. //</editor-fold>
  96.  
  97.  

Y la clase "runnable"

Código
  1. //<editor-fold defaultstate="collapsed" desc="Clase runnable">
  2. public abstract class runnable extends Thread implements Runnable {
  3.  
  4.    volatile boolean running=true;
  5.  
  6.    //<editor-fold defaultstate="collapsed" desc="Constructor vacio">
  7.    public runnable(){
  8.  
  9.    }//</editor-fold>
  10. }
  11. //</editor-fold>
  12.  
  13.  



Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 19 Junio 2011, 18:57 pm
Synchronized se usa para acceder en exclusión mutua a una sección de código (aunque también se pueden declarar métodos como synchronized), es decir, que tan solo un objeto pueda acceder al mismo tiempo al bloque que se declara como synchronized.

Te cito unos apuntes que tengo donde hace una explicación muy breve:

Citar
Synchronized aplicado a un bloque de código:

A veces no nos interesa que todo el método sea sincronizado, sino solamente una parte de él. En ese caso, synchronized se puede usar sobre un bloque de código. Para ello es necesario indicar el objeto que será utilizado como cerrojo. Esto hace que el bloque de código se ejecute en exclusión mutua con cualquier bloque de código o método sincronizado sobre el mismo objeto.

Synchronized aplicado a un método:

Un método puede llevar el modificador synchronized. Todos los métodos con este modificador se ejecutarán en exclusión mutua. Cuando un método sincronizado se está ejecutando sobre un objeto concreto, ningún otro método sincronizado podrá ejecutarse sobre ese mismo objeto. Sin embargo, cualquier otro método no sincronizado sí podrá ejecutarse.

Synchronized nunca he llegado a comprenderlo del todo, pero la forma en la que lo estás usando creo que no es correcta. En el caso en que usas this como cerrojo no sería correcto, ya que, si no me equivoco, debes usar un objeto que sea común a todos los hilos. De la forma en que tu lo haces cada hilo es su propio cerrojo, y eso creo, y repito creo, no es correcto.

Por otro lado, y espero no te lo tomes a mal, el código lo veo algo lioso, no se, no le veo una estructura clara por así decirlo. Supongo que serán pruebas que estás realizando, pero creo que te convendría más organizarlo mejor (todo esto desde mi punto de vista, obviamente xD). Otra cosa, ¿porque heredas de Thread e implementas Runnable? Supuestamente con realizar alguna de las dos te valdría, es decir, o heredas de Thread, o implementas la interfaz Runnable.

En fin, esas son mis opiniones.

Suerte y saludos.


Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 20 Junio 2011, 01:39 am
Heredo de Thread e implemento Runnable para no instanciar Thread y pasarle la instancia de la subclase de Runnable como argumento, no se como hacerlo de otra forma xD, bueno, lo de synchronized, entendí la parte de que un metodo synchronized no puede ser accedido por mas de un miembro al mismo tiempo, lo que no entendi es lo de que una parte del metodo puede ser synchronized, ok, ya quizas eso lo entiendo solo una parte del bloque de codigo del metodo puede ser accedida solo por un miembro al mismo tiempo, pero lo que no entendi fue lo de los cerrojos xD

Bueno agradezco las respuestas, estoi un poko corto de tiempo, sorry si no me se explicar bien y tambien me disculpo por que me cueste un poko entender xD.

Saludos  ;)


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 20 Junio 2011, 03:19 am
Heredo de Thread e implemento Runnable para no instanciar Thread y pasarle la instancia de la subclase de Runnable como argumento, no se como hacerlo de otra forma xD

Pues heredas de Thread directamente, implementas el método
Código
  1. public void run()
y luego creas un objeto de tu clase y se lo asignas a un Thread. Por ejemplo imaginate que creas esta clase:

Código
  1. public class HiloSumador extends Thread{
  2.        private String identificador;
  3.        private int cantidad;
  4.  
  5.        public HiloSumador(String id){
  6.                identificador = id;
  7.                cantidad = 0;
  8.        }
  9.  
  10.        public void run(){
  11.                for(int i = 0;i<20;i++)
  12.                        cantidad++;
  13.                System.out.println("La suma es: "+cantidad);
  14.        }
  15.  
  16.        public static void main(String[] args){
  17.                Thread hilo1 = new HiloSumador("Hilo1");
  18.                hilo1.start();
  19.        }
  20.  
  21. }

A la hora de crear los objetos lo haces así:

Thread hilo1 = new HiloSumador("Hilo1");

y con eso ya lo tienes hecho.

pero lo que no entendi fue lo de los cerrojos xD

"Cerrojo" es un poco la terminología, con eso lo que se quiere decir es que ese objeto actúa como si fuese una cerradura, solo deja pasar a un hilo al mismo tiempo.

Espero te sirva. Saludos.

Te vuelvo a insistir, con un semáforo se controla mejor (o por lo menos a mi me parece más sencillo de entender) que con Synchronized. Si quieres saber algo más del tema pregunta!.



Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 21 Junio 2011, 23:40 pm
Te funciona lo que hiciste?

Es que la clase java.lang.Thread no tiene una variable que se llame identificador, por eso no habia pensado en castear a la superclase, todavia hago esto:

Thread t=new Thread(new runnable);

Heredando en runnable de Thread e implementando Runnable, hay otra forma?


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 22 Junio 2011, 03:19 am
A ver, antes de ponerte a trastear hilos en Java creo que sería bastante conveniente que leyeses sobre Java. Para el caso, herencia, que pasa con los atributos que se heredan, si se pueden añadir atributos, si se pueden redefinir los métodos, etc...hay muchísimas cosas y muuuuuuuuy interesantes sobre la herencia de Java, así que te recomiendo la lectura ;)

El ejemplo que te puse no se si compila, pero vamos el código en si es correcto. Tu heredas de la clase Thread, declaras todos los atributos que quieras, los inicializas, implementas el método run() y listo, ya tienes tu thread preparado para ejecutar.

Echando un vistazo ahora a los manuales de la clase Thread, en el ejemplo que yo te puse no sería necesario declarar un atributo String identificador, ya que por lo que veo existe un constructor de la clase Thread que le pasas un String  y ese es el nombre del thread (que viene a ser lo mismo, si no me equivoco, que el identificador que yo declaraba). Por tanto realizando al principio del constructor de la clase ejemplo que hice esta llamada: super("Hilo1"); bastaría.

Yo ya te digo, esta forma la veo la más sencilla, es la que he aprendido (a parte de implementar la interfaz Runnable, crear objetos de la clase que implementa la interfaz y crear objetos de tipo Thread pasandole como argumento al constructor el objeto anterior) y la veo bastante más intuitiva, pero...cada cual lo hace como quiere.

Saludos.


Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 22 Junio 2011, 08:00 am
De partida no es lo mismo agregar un nombre a un Thread que una variable identificadora o un contador o un valor booleano, etc... si vas a responder mi ultima pregunta te lo agradecere, pero lo que dices no tiene absolutamente nada que ver, y el codigo que pusiste si suelta error en tiempo de ejecucion por que no existe tal variable en la clase Thread, aunke pensandolo nisikiera es necesario hacer ese cast... y no me mandes a leer tutoriales por algo tan basico como pasar un argumento a la superclase, si no viste estoi preguntando otra cosa...

Saludos  ;)


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 22 Junio 2011, 14:10 pm
De partida no es lo mismo agregar un nombre a un Thread que una variable identificadora o un contador o un valor booleano, etc... si vas a responder mi ultima pregunta te lo agradecere, pero lo que dices no tiene absolutamente nada que ver, y el codigo que pusiste si suelta error en tiempo de ejecucion por que no existe tal variable en la clase Thread, aunke pensandolo nisikiera es necesario hacer ese cast... y no me mandes a leer tutoriales por algo tan basico como pasar un argumento a la superclase, si no viste estoi preguntando otra cosa...

Saludos  ;)

Vamos a ver, porque no estamos confundiendo. Si pongo este código en vez del anterior (el cual también compila y funciona perfectamente):

Código
  1. public class HiloSumador extends Thread {
  2.  
  3. private String identificador;
  4. private int cantidad;
  5.  
  6. public HiloSumador(String id) {
  7. super(id);
  8. identificador = id;
  9. cantidad = 0;
  10. }
  11.  
  12. public void run() {
  13. for (int i = 0; i < 20; i++)
  14. cantidad++;
  15. System.out.println("La suma es: " + cantidad);
  16. System.out.println(identificador);
  17. System.out.println(getName());
  18. }
  19.  
  20. public static void main(String[] args) {
  21. Thread hilo1 = new HiloSumador("Hilo1");
  22. hilo1.start();
  23. }
  24.  
  25. }
  26.  

La salida por pantalla es:

Código:
La suma es: 20
Hilo1
Hilo1

Así que es lo mismo ponerle el nombre, que añadir una variable llamada "identificador" para llamar al hilo de alguna forma. ¿Qué no existe la variable y suelta error en tiempo de ejecución? Te vuelvo a decir que mires más cosas de Java, ¿como no va a existir una variable que te declaras como atributo de tu clase? Existen las dos, identificador y cantidad, porque las he declarado. Aunque haya herencia, yo estoy añadiendo los atributos que yo necesito para que mi hilo funcione. Así que no entiendo de donde te has sacado que falla en tiempo de ejecución por un lado, y que no existe esa variable por otro.

No se a que te refieres con eso de cast, si te refieres a "casting" yo no veo ninguno en el código así que...será otra cosa a lo que te refieres.

Por último ya te he respondido a tu pregunta:
Heredando en runnable de Thread e implementando Runnable, hay otra forma?

Se puede hacer como te he mostrado en este código y en el anterior (que es la misma forma). No tiene sentido (y que me corrijan por favor si me equivoco alguien que lea esto) heredar de Thread, e implementar la interfaz Runnable, ya que si te vas y miras un poco la documentación de Thread: http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html verás que pone "All implemented interfaces: Runnable".

Siendo más sencillo, a tu pregunta respondo: Sí, se puede hacer de dos formas. Heredando de Thread e implmentando el método run(). O implementando la interfaz Runnable e implementando el método Run.

Saludos  ;)


Título: Re: [Threads] wait() y notify()
Publicado por: klaine en 23 Junio 2011, 01:31 am
Pensansolo bien funciona, pero no instanciandolo de la forma que dijiste, por eso me confundí

Thread t=new HiloSumador();

Al mostrar t.identificador (habiendolo cambiado a public) muestra, no existe la variable identificador en java.lang.Thread XP

Bueno, gracias de todos modos, saludos


Título: Re: [Threads] wait() y notify()
Publicado por: Valkyr en 23 Junio 2011, 02:47 am
No he probado eso que dices de ponerlo a public y mostrarlo así, pero vamos, eso es una tontería porque si quieres acceder a algún atributo de la clase, declaras su método get y punto. Además, es lógico que falle porque cuando intentas acceder a un atributo de clase directamente se hace por su parte estática y no dinámica, y evidentemente la clase Thread no tiene un atributo llamado identificador. Asíais si lo que quieres hacer es poner atributos a public esta forma fallaría, pero vamos, en el 99,9% de los casos se recomienda declaralos privare.

Además, todo lo que he intentado explicaste ha sido lo que he aprendido en una asignatura de programación concurrente y distribuida, azoque puedo asegurarte que esta bien.

Saludos