style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Hilos en Java, problemas con uso de Thread

Saludos compañeros:

Estoy tratando de implementar la carrera de la libre y el conejo usando hilos, pero cuando ejecuto el programa siempre da el mismo resultado y la liebre y el conejo se mueven al mismo tiempo. Según entendí al leer sobre el significado de los hilos esta ejecución debería ser siempre diferente dependiendo del tiempo que el asigne el sistema operativo a cada proceso en el hilo.Traté de usar el concepto de SwingWorker pero me dio lo mismo y no entiendo bien por qué,así que me quedé con esta versión del problema. Uso java 6, actualización 41 y construyo las ventanas con Netbeans.

Anexo el código de la Clase Liebre (porque el de la tortuga es idéntico, sólo cambio la imagen y se encuentra en una clase llamada Tortuga) y el código de la llamada de los hilos desde la ventana.

public class Liebre implements Runnable {

    private JLabel etiqueta;

     public Liebre(JLabel etiqueta){
        this.etiqueta = etiqueta;
      }
 
     public void run(){
        int cont=0;
        int y=etiqueta.getY();
        while(cont < 8)
            {
               try
                {  Thread.sleep(1500);
                   etiqueta.setLocation(etiqueta.getX()+51,y);
                }
               catch (InterruptedException e) {

                }
             cont++;
           }
         }
}

package gui;
import dominio.Liebre;
import dominio.Tortuga;
import javax.swing.ImageIcon;

public class Carrera extends javax.swing.JFrame {

    /** Creates new form Carrera */
    public Carrera() {
        initComponents();
         this.setLocationRelativeTo(null);
         this.setIconImage(new ImageIcon("src/imagenes/pingui.png").getImage());
         this.setResizable(false);
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        tortu = new javax.swing.JLabel();
        cone = new javax.swing.JLabel();
        aviso = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        arrancar1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Carrera loca");
        setAlwaysOnTop(true);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
        jPanel1.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        tortu.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imagenes/Tortuga.gif"))); // NOI18N
        jPanel1.add(tortu, new org.netbeans.lib.awtextra.AbsoluteConstraints(41, 63, 80, -1));

        cone.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imagenes/Conejo.gif"))); // NOI18N
        jPanel1.add(cone, new org.netbeans.lib.awtextra.AbsoluteConstraints(40, 180, 80, -1));
        jPanel1.add(aviso, new org.netbeans.lib.awtextra.AbsoluteConstraints(310, 330, 180, 20));

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imagenes/meta2.png"))); // NOI18N
        jPanel1.add(jLabel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(400, 30, 60, 280));
        jPanel1.add(jSeparator1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 160, 510, -1));

        getContentPane().add(jPanel1, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 10, 530, 340));

        arrancar1.setText("Arrancar");
        arrancar1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                arrancar1ActionPerformed(evt);
            }
        });
        getContentPane().add(arrancar1, new org.netbeans.lib.awtextra.AbsoluteConstraints(250, 370, -1, -1));

        pack();
    }// </editor-fold>
    private void arrancar1ActionPerformed(java.awt.event.ActionEvent evt) {                                          
       
        Thread liebre = new Thread(new Liebre(cone));
        Thread tortuga = new Thread(new Tortuga(tortu));
        tortuga.start();
        liebre.start();
        arrancar1.setEnabled(false);
    }                                        

    /**
    * @param args the command line arguments
    */

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Carrera().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    private javax.swing.JButton arrancar1;
    private javax.swing.JLabel aviso;
    private javax.swing.JLabel cone;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JLabel tortu;
    // End of variables declaration

}

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

liebre y conejo

La liebre y el conejo se mueven al mismo tiempo... será porque son prácticamente la misma cosa?

Liebre y conejo

Es que ejecuté el código sin la ventana y unas veces gana la liebre y otras veces gana la tortuga, es decir, no tiene el mismo comportamiento aún cuando tengan los mismo milisegundos asignados y cada vez que se ejecuta es distinto el movimiento. Cuando agregué la ventana en Netbeans dejó de funcionar y la verdad ni idea del por qué

Imagen de ezamudio

indeterminado

Pues así debe ser; si tienes dos hilos con la misma prioridad y que hacen exactamente lo mismo, y ambos los inicias al mismo tiempo, no tienes manera de saber cuál va a terminar primero.

Si quieres que la tortuga siempre termine después, tienes varias opciones:

- Puedes ponerle un retraso (si ambos hilos tienen retraso, debe ser mayor en el caso de la tortuga)
- Puedes ponerle una prioridad más baja al hilo, aunque eso realmente TAMPOCO garantiza que vaya a terminar después...
- Puedes darle a la tortuga una referencia a la liebre para que justo antes de llegar a la meta, le haga join() y así espere a que la liebre llegue a la meta antes de que ella misma la cruce. Este sería el único método que garantiza que la tortuga llegue después, aunque se vea raro si la tortuga le gana a la liebre y luego se espera un paso antes de la meta a que la liebre gane...

liebre y conejo

Efectivamente, me fui por la opción que me indicaste de colocarle un mayor tiempo de retraso a la tortuga y siempre llega después del conejo; pero no logro descubrir la razón por la cual el código anterior que estaba corriendo directamente en la área de salida (output) de netbeans a pesar de tener tiempos iguales de retraso siempre generaba salidas distintas y ahora con la ventana hecha con el JFrame Form su comportamiento se vuelve predecible y siempre es la misma salida. No se si tenga que ver con el hecho de que la ventana como tal tiene su propio hilo, es decir, no estoy segura de que esta parte del código esté afectando a los hilos de la tortuga y el conejo.

public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Carrera().setVisible(true);
            }
        });

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">