Mostrando las entradas con la etiqueta Hilos. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Hilos. Mostrar todas las entradas

martes, 2 de septiembre de 2014

Cronómetro en java

Recientemente en un proyecto me fue necesario crear un cronómetro, o la simulación de uno, para poder hacer esto y mostrar en pantalla, fue necesario usar hilos, no hay de otra.
EL mini-cronómetro que le mostraré a continuación es sencillo, cuando le dan clic en el botón iniciar cronómetro, lógicamente, el cronómetro inicia, y se bloquea el botón, esto para evitar que se genere un nuevo hilo.
El botón reiniciar cronómetro hace exactamente eso.
La interfaz es sencilla, es la siguiente:

La imagen de arriba, muestra la interfaz que cuenta el cronómetro, como pueden ver, es una aplicación muy simple, la clase Tiempo contiene los métodos que son necesarios para poder usar el cronómetro, en caso de que deseen modificar a su conveniencia no hay problema de ello.
El proyecto lo pueden descargar de aquí, si los links están rotos, por favor avisarme para poder corregirlos.
# Comentar es algo bueno, criticar es mucho mejor.

lunes, 4 de agosto de 2014

Reproducir sonido en segundo plano usando hilos en java

Es posible que necesiten reproducir algún sonido en alguna de sus aplicaciones. Hace poco estaba desarrollando un juego en java, y necesitaba reproducir sonidos. Una manera de hacer es la siguiente.
Por ahora no tiene los métodos de pausar, parar, etc.
Será necesario crear una clase que se llama ReproducirSonidos y la otra llamada PruebasSonidos que es la clase principal.

Nota: Dentro de la carpeta del proyecto, es necesario crear una carpeta llamada sonidos y almacenen ahí los sonidos que usen en su proyecto.



/*
 * Nombre de la clase: ReproducirSonidos
 * Descripción: Controla el sonido que se esté reproduciendo, utilizando un hilo
 *              sin opciones de pausea, stop o reanudar, simplemente lo ejecuta
                y comienza la reproducción de la canción, y espera hasta que finalice.
 */
package pruebassonidos;

import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 *
 * @author gsu Jesús Fernando Merino Merino
 */
public class ReproducirSonidos extends Thread{
    String mensaje;
    String sonido;
    int timeRep=0;
    boolean stop=false;
    public ReproducirSonidos(){
        mensaje="Hola";
    }
    public ReproducirSonidos(String sonido){
        this.sonido=sonido;
    }
    public ReproducirSonidos(String sonido,boolean stop){
        this.sonido=sonido;
        stop=false;
    }
    public void run(){
        repSonido(sonido);
        System.out.println("Este proceso ha terminado:"+this.getName());
    }

    public void setMensaje(String msj){
        this.mensaje = msj;
    }
    
    public void repSonido(String sonido){
        SourceDataLine soundLine = null;
        int BUFFER_SIZE = 64*1024;  // 64 KB
        // Set up an audio input stream piped from the sound file.
        try {
           File soundFile = new File(sonido);
           AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
           AudioFormat audioFormat = audioInputStream.getFormat();
           DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
           soundLine = (SourceDataLine) AudioSystem.getLine(info);
           soundLine.open(audioFormat);
           soundLine.start();
           int nBytesRead = 0;
           byte[] sampledData = new byte[BUFFER_SIZE];
           while (nBytesRead != -1) {
              nBytesRead = audioInputStream.read(sampledData, 0, sampledData.length);
              if (nBytesRead >= 0) {
                 // Writes audio data to the mixer via this source data line.
                 soundLine.write(sampledData, 0, nBytesRead);
              }
           }
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
            System.err.println("Error: "+ex.getMessage());
        } finally {
           soundLine.drain();
           soundLine.close();
        }
    }
}

Clase principal del proyecto...
/*
 * Clase: PruebaSonidos
 * Descripción: Programa que reproduce una cación en segundo plano, usando hilos.
 */
package pruebassonidos;


/**
 *
 * @author gXfer Jesus Fernando Merino Merino
 */
public class PruebasSonidos {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ReproducirSonidos reproducir = new ReproducirSonidos("sonidos/ajws.au");
        reproducir.start();
        System.out.println("Después de la canción");
    }
}

Pueden descargar el proyecto aquí. Gracias por visitar, si tienen dudas comenten por favor.

domingo, 22 de junio de 2014

Recibir datos desde arduino utilizando una interfaz en java

Ejecutar jbuttons desde arduino al presionar botones físicos.

Recientemente desarrollé una aplicación utilizando arduino para manipular una interfaz gráfica a través de botones físicos conectados a arduino. La interfaz gráfica fue hecha en java, utilizando netbeans 8.0 en fedora 20.

Fue la primera vez que utilicé arduino, además también fue la primera vez que conecté arduino con java.
Cuando se usa linux, por lo general se complica lo suficiente al querer ejecutar un programa, la mayoría de las veces es por cuestiones de permisos de archivos o permisos de ejecución de archivos, así también como los permisos que tenga el directorio donde está almacenado dicho ejecutable.

Antes de comenzar es necesario que tengan instalado:

  • Java
  • Arduino
  • Librerias de arduino
  • Netbeans 7.4 O superior


  • Tomaré en cuenta que ya tienen instalado los paquetes necesarios y continuaré con la explicación de la pequeña aplicación que he creado.
    Se utilizó la tarjeta arduino uno. 

    Descripción del proyecto: crear una interfaz en java utilizando jframe con 4 botones, cada botón realizará un determinada acción. Realizar un pequeño tablero con 4 pushbuttons conectados a arduino. La idea es que cuando se presione un botón en el tablero se ejecute la acción de un botón en la interfaz desarrollada en java. De tal modo que el dispositivo de interacción sea el tablero con botones.

    Realización:
    Primero se creará la interfaz gráfica, lo dejaré a su criterio, es un jframe que debe de tener 4 botones.

    Pueden crear una interfaz parecida a la imagen de arriba o hacer una que les convenga.
    Los botones físicos que estarán conectados a arduino pueden diseñarlos o colocarlos en un protoboard.
    El circuito es el siguiente:


    El programa que estará codificado en arduino es el siguiente:
    //se declaran los pines de entrada que se usaran
    const int buttonPin = 2;     //Se reserva el numero de pin de entrada
    const int buttonPin2 = 3;    //Se reserva el numero de pin de entrada
    const int buttonPin3 = 4;    //Se reserva el numero de pin de entrada
    const int buttonPin4 = 5;    //Se reserva el numero de pin de entrada

    const int ledPin =  12;      //Se reserva el numero de pin de entrada
    const int ledPin2 =  11;     //Se reserva el numero de pin de entrada
    const int ledPin3 =  10;     //Se reserva el numero de pin de entrada
    const int ledPin4 =  9;      //Se reserva el numero de pin de entrada
    //variables que cambian de valor durante la ejecucion
    int buttonState = 0;         //variable que almacena el valor del estado del pin de entrada buttonPin
    int buttonState2 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin2
    int buttonState3 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin3
    int buttonState4 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin4

    int buttonStateFinal1 = 0;         //variable que almacena el valor del estado del pin de entrada buttonPin
    int buttonStateFinal2 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin2
    int buttonStateFinal3 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin3
    int buttonStateFinal4 = 0;        //variable que almacena el valor del estado del pin de entrada buttonPin4

    int sensorPin = A0;          //entrada del sensor de ritmocardiaco se declara el pin que se usara
    int sensorValue = 0;         //variable en la que se almacena el valor leido del pin de entrada del sensor

    int leerDatos=0; //variable para indicar si se continua leyendo o no;
    void setup(){
      //Serial.begin(115200); //Open the serial port
      Serial.begin(9600); //se abre el puerto serial
      //se inicializan los pines salida en caso de que se necesiten
      pinMode(ledPin, OUTPUT);
      pinMode(ledPin2, OUTPUT);
      pinMode(ledPin3, OUTPUT);
      pinMode(ledPin4, OUTPUT);
      //se inicializan los pines de entrada y que seran los que se tienen que leer
      //para saber cual es estado de cada boton
      pinMode(buttonPin, INPUT);
      pinMode(buttonPin2, INPUT);
      pinMode(buttonPin3, INPUT);
      pinMode(buttonPin4, INPUT);
    }

    void loop(){
        //leerDatos = Serial.read();
        //if(leerDatos=='1'){
          // se leen los estados de cada uno de los pines de entrada
          buttonState = digitalRead(buttonPin);
          buttonState2 = digitalRead(buttonPin2);
          buttonState3 = digitalRead(buttonPin3);
          buttonState4 = digitalRead(buttonPin4);
          //sensorValue = analogRead(sensorPin);
          // verifica el valor leido de cada pin
          // si el valor es 1 los leds se encienden, en caso contrario
          // el led continua apagado
          if(buttonState == HIGH){
            digitalWrite(ledPin4, HIGH);
            buttonStateFinal1=1;
          }else{
            digitalWrite(ledPin4, LOW);
            buttonStateFinal1=0;
          }
          if(buttonState2 == HIGH){
            digitalWrite(ledPin3, HIGH);
            buttonStateFinal2=2;
          }else{
            digitalWrite(ledPin3, LOW);
            buttonStateFinal2=0;
          }
          if(buttonState3 == HIGH){
            digitalWrite(ledPin2, HIGH);
            buttonStateFinal3=3;
          }else{
            digitalWrite(ledPin2, LOW);
            buttonStateFinal3=0;
          }
          if(buttonState4 == HIGH){
            digitalWrite(ledPin, HIGH);
            buttonStateFinal4=4;
          }else{
            digitalWrite(ledPin, LOW);
            buttonStateFinal4=0;
          }
          //se imprimen los valores leidos a pantalla, este proceso es necesario
          //de aqui depende para que desde java se puedan leer dichos valores
          Serial.println(buttonStateFinal1);
          Serial.println(buttonStateFinal2);
          Serial.println(buttonStateFinal3);
          Serial.println(buttonStateFinal4);
          //Serial.println(sensorValue);
          //el programa se espera un tiempo de 100 milisegundos antes de volver
          //a realizar una lectura, no es tan necesario el retardo, para
          //para que java no se le haga pesado, es necesario un retardo
        //}
        delay(100); /*detiene el programa por 100 milisegundos antes de volver a leer los puerto*/

    }

    El código de arduino parece mucho, pero las impresiones son más bien para saber qué está pasando en cada momento, así que descuiden, dependiendo de la necesidad que tengan, así pueden ir modificando dicho código.

    Después de que su código ya esté codificado en la tarjeta, procedemos a crear la aplicación en java.

    La clase principal, que se mostró en la primera imagen lleva el siguiente código. En realidad pueden crear sólo un jframe con 4 botones o los que consideren necesarios y listo.

    /*
     * La clase VentanaJuego que extiende jframe, contiene el juego principal,
        es decir, ésta clase es donde se muesra en sí todo el proceso del juego.
     */

    package ventanasScoop;

    import java.util.logging.Level;
    import java.util.logging.Logger;

    /**
     *
     * @author neo Jesús Fernando Merino Merino
     */
    public class VentanaJuego extends javax.swing.JFrame implements  Runnable{

        /**
         * Se crea un objeto de tipo VentanaJuego para que reciba el objeto que le
         * envian de la interfaz iniciarScoop, dicho objeto.
         * Es aquí donde se crea el objeto que se usará para leer los datos desde arduino
         */
        /*Objeto creado para manipular la interfaz del juego scoop*/
        private VentanaJuego jugarJuego;
        /*Se crea el objeto de tipo DatosJugador dicho objeto almacenará toda la
        información necesari del jugador que inice sesión para jugar*/
        private DatosJugador datosJugador;
        /*variable que almacena la interfaz de inicio de sesión*/
        private iniciarScoop inicioSesion;
        /*variable que se usa para iniciar el sensado de la tarjeta arduino
        básicamente es un hilo que se lanza, y que sólo se consultan los datos
        almacenados en un vector declarado en dicha clase*/
        //LecturaFromArduino lectArduino=new LecturaFromArduino();
        private LecturaFromArduino lectArdReciv;
        
        /*variable que debe de estar activada para poder realizar validaciones cuando
        el usuario esté sobre esta ventana*/
        private boolean permitBotArdVentJueg=true;
        
        /*variable que almacena el hilo que se pone en ejecución para relizar la validadión
        de los datos que se reciben al presionar un botón en el tapete*/
        Thread obtDatArd;
        
        public VentanaJuego() {
            initComponents();
        }
        public VentanaJuego(VentanaJuego ventJuego,DatosJugador datJugador) {
            initComponents();
        }
        public VentanaJuego(iniciarScoop inicio,DatosJugador datJugador) {
            /*constructor que recibe el objeto de inicio de sesión y los datos del jugador*/
            initComponents();
            setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
            setLocationRelativeTo(null);
            setDatosJugador(datJugador);
            setInicioSesion(inicio);
            visulizarNomJugadorVentana();
        }
        public VentanaJuego(iniciarScoop inicio,DatosJugador datJugador, LecturaFromArduino lectArd) {
            /*constructor que recibe el objeto de inicio de sesión, los datos del jugador
            y el objeto que inicia la lectura desde arduino, para poder acceder al método
            que retorna el arreglo de datos obtenidos desde arduino*/
            initComponents();
            setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
            setLocationRelativeTo(null);
            setDatosJugador(datJugador);
            setInicioSesion(inicio);
            visulizarNomJugadorVentana();
            setLectArduReciv(lectArd);
            iniciaValidBotArd();
        }
        public void ninioONinia(DatosJugador datosJugador){
            /*método que valida si el usuario que a accedio es niño o niña, para modificar
            el color de los íconos*/   
        }
        public final void visulizarNomJugadorVentana(){
            /*se establece el nombre del jugador en el jlabel*/
            jlDatosJugador.setText("Bienvenido: "+datosJugador.getNomJugador());
        }
        /*inicia declaración de métodos de set y get de los atributos de esta interfaz*/
        public void setVentanaJugador(VentanaJuego ventana){
            jugarJuego=ventana;
        }
        public final void setDatosJugador(DatosJugador datos){
            datosJugador=datos;
        }
        public final void setInicioSesion(iniciarScoop inicio){
            inicioSesion=inicio;
        }
        public void setPermitBotArdVentJue(boolean permitir){
            permitBotArdVentJueg=permitir;
        }
        public final void setLectArduReciv(LecturaFromArduino let){
            /*inicializa el objeto recibido del sensado desde arudino*/
            lectArdReciv=let;
        }
        public boolean getPermitBotArdVentJue(){
            return permitBotArdVentJueg;
        }
        /*finaliza declaración de métodos de set y get de los atributos de esta interfaz*/
        
        public void detenerValidBotVentJuego(boolean  estado){
            /*detiene o reanuda la valición de los resultados que se obtienen de los
            hilos, dependiendo si el usuario se encuentra en la ventanaJuego*/
            permitBotArdVentJueg=estado;
        }
        public final void iniciaValidBotArd(){
            obtDatArd=new Thread(this);
            obtDatArd.start();
        }              

        private void jbSalirActionPerformed(java.awt.event.ActionEvent evt) {                                        
            new SalirJuego(this, true,datosJugador,inicioSesion,lectArdReciv).setVisible(true);
        }                                       
        

        // Variables declaration - do not modify                     
        private javax.swing.JButton jbAyuda;
        private javax.swing.JButton jbIniciar;
        private javax.swing.JButton jbRanking;
        private javax.swing.JButton jbSalir;
        private javax.swing.JLabel jlDatosJugador;
        private javax.swing.JLabel jlTutorial;
        private javax.swing.JPanel jpBackJuego;
        // End of variables declaration                   

        @Override
        public void run() {
            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            /*método que ejecuta acciones en la ventana de menú del jugador, de acuerdo
            a los datos que se reciben de los botones que se presionan desde el tapete*/
            String [] datosArd;
            while (permitBotArdVentJueg) {            
                datosArd = lectArdReciv.getDatRecArduino();
                //System.out.println("Datos de arduino: "+datosArd[0]+"  "+datosArd[1]+"  "+datosArd[2]+"  "+datosArd[3]);
                System.out.println("Datos de arduino: "+datosArd[0]);
                /*proceso de validar qué número de botón se ha presionado*/
                switch(datosArd[0]){
                    case "1":
                        jbIniciar.doClick();
                        break;
                    case "2":
                        jbRanking.doClick();
                        break;
                    case "3":
                        jbAyuda.doClick();
                        break;
                    case "4":
                        jbSalir.doClick();
                        break;
                    default:
                        break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(VentanaJuego.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }


    }

    Básicamente las funciones que están de azul, son las más importantes.
    En primera se inicia un un hilo que crea un objeto de tipo zyncronized, el cual lee constantemente desde el puerto que esté conectado arduino, luego valida qué botón fue el que se pulsó, de acuerdo al número que se recibe de arduino.
    Y lo que se hace es, que se ejecuta el doclic() del botón que se necesario. Y listo.
    La clase de arduino es la siguiente:
    package ventanasScoop;

    import gnu.io.CommPortIdentifier;
    import gnu.io.PortInUseException;
    import gnu.io.SerialPort;
    import gnu.io.SerialPortEvent;
    import gnu.io.SerialPortEventListener;
    import gnu.io.UnsupportedCommOperationException;
    import static java.awt.image.ImageObserver.ERROR;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.util.Enumeration;
    import java.util.TooManyListenersException;

    /**
     *
     * @author neo Jesus Fernando Merino
     */
    public class LecturaFromArduino implements SerialPortEventListener{
        private OutputStream Output = null;
        private BufferedReader Input = null;
        private SerialPort serialPort;
        private String[] inputLine;
        private final String PORT_NAME = "/dev/ttyUSB0";
        private static final int TIME_OUT = 110;
        private static final int DATA_RATE = 9600;
        int cont=0;

        public LecturaFromArduino() {
            this.inputLine = new String[5];
        }
        public String[] getDatRecArduino(){
            /*retorna el arreglo que contien los datos que se reciben desde Arduino*/
            return inputLine;
        }
        @Override
        public synchronized void serialEvent(SerialPortEvent oEvent) {
            if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE){
                try{
                    inputLine[0]=Input.readLine();
                    //inputLine[1]=Input.readLine();
                    //inputLine[2]=Input.readLine();
                    //inputLine[3]=Input.readLine();
                    //System.out.println("Datos recibidos: "+inputLine[0]+" : "+inputLine[1]+" : "+inputLine[2]+" : "+inputLine[3]);
                }catch (IOException e){
                    System.err.println("Erorr función serialEvent: "+e.getMessage());
                }
            }
        }
        
        public void ArduinoConnection() {
            CommPortIdentifier portId = null;
            Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
            while (portEnum.hasMoreElements()) {
                CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
                if (PORT_NAME.equals(currPortId.getName())) {
                    portId = currPortId;
                    break;
                }
            }
            if (portId == null) {
                System.exit(ERROR);
                return;
            }
            try {
                serialPort = (SerialPort) portId.open(this.getClass().getName(), TIME_OUT);
                serialPort.setSerialPortParams(DATA_RATE,
                        SerialPort.DATABITS_8,
                        SerialPort.STOPBITS_1, /*SerialPort.STOPBITS_1*/
                        SerialPort.PARITY_NONE);
                Output = serialPort.getOutputStream();
                Input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
                serialPort.addEventListener(this);
                serialPort.notifyOnDataAvailable(true);
            } catch (PortInUseException | UnsupportedCommOperationException | IOException | TooManyListenersException e) {
                System.err.println("Error ArduinoConnection: "+e.getMessage());
            }
        }
        private void EnviarDatos(String data) {
            try {
                Output.write(data.getBytes());
            } catch (IOException e) {
                System.exit(ERROR);
            }
        }

        private void RecibirDatos() throws IOException {
            int Output1;
            Output1 = Integer.parseInt(Input.readLine());
            cont= Integer.parseInt(Input.readLine());
            System.out.println("Ouput1: "+Output1 +" valor recibido: "+cont);
        }

    }

    Ojo, necesitarán la librería librxtxSerial.so, también el jar RXTXcomm.jar, y lo colocan en la carpeta lib de su proyecto, y pues claro importan los jar para que funcione.
    Además en la pestaña propiedades de su proyecto deben especificar la ruta en donde se encuentra la librería librxtxSerial.so en la sección run en la descripción VM options: de preferencia muevan la librería librxtxSerial.so a la carptea lib de su proyecto, y coloquen la siguiente ruta.

    -Djava.library.path="../scoopControlButtons/lib/"


    Ejecutan su proyecto y deberá funcionar, en caso de que no, por favor envíenme un msj para aclarar dudas.

    jueves, 19 de junio de 2014

    Java - Hilos Thread JFrame

    Crear y arrancar el hilo desde una clase que extiende jframe y que implemente Runanble

    Para crear un hilo en java, primero debemos hacer una clase que implemente la interface Runnable  y además extienda la interfaz  JFrame  
    Crear un nuevo proyecto, agregar un jframe, dentro del jframe un jpanel, en el jpanel agregar dos botones, uno para salir y el otro para lanzar el hilo
    La interfaz quedará de la siguiente manera:

    package ThreadJFrame;
    
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    /**
     *
     * @author neo
     */
    public class Principal extends javax.swing.JFrame implements Runnable{
        boolean seguirHilo=false;
        boolean hiloIniciado=false;
        Thread hilo;
        int cont=0;
        /**
         * Creates new form Principal
         */
        public Principal() {
            initComponents();
        }        
    
        private void jbLanzarHiloActionPerformed(java.awt.event.ActionEvent evt) {
                iniciarHilo();
                if(seguirHilo){
                    pararHIlo(false);
                    jbLanzarHilo.setText("Reanudar hilo");
                }else{
                    pararHIlo(true);
                    jbLanzarHilo.setText("Detener hilo");
                }
        }                                            
    
        private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
            System.exit(0);
        }                                        
    
        /**
         * @param args the command line arguments
         */
        public static void main(String args[]) {
            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Principal().setVisible(true);
                }
            });
        }
        /*método para iniciar el hilo*/
        public void iniciarHilo(){
            hilo=new Thread(this);
            hilo.start();
            hiloIniciado=true;
        }
        /*método para parar el hilo*/
        public void pararHIlo(boolean estado){
            seguirHilo=estado;
        }
        // Variables declaration - do not modify                     
        private javax.swing.JButton jButton1;
        private javax.swing.JLabel jLabel1;
        private javax.swing.JPanel jPanel1;
        private javax.swing.JScrollPane jScrollPane1;
        private javax.swing.JTextArea jTextArea1;
        private javax.swing.JButton jbLanzarHilo;
        // End of variables declaration                   
    
        @Override
        public void run() {
            /*aquí va el código que se ejecutará en el hilo*/
            while(seguirHilo){
                System.out.println(cont+" :Hola mundo desde java usando hilos");
                cont++;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
    
    Lo que esté en el método run() es lo que se ejecutará en un hilo separado.
    Cuando queramos que empiece a ejecutarse, creamos una instancia de la clase Thread pasándole una instancia de MiRunnable y la arrancamos
    public void iniciarHilo(){
            hilo=new Thread(this);
            hilo.start();
            hiloIniciado=true;
    }

    Dormir un hilo

    Para dormir un hilo durante un cierto tiempo, basta con llamar al método sleep(). Puesto que este método lanza una excepción, debemos capturarla.
    try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
                }

    Terminar un hilo

    Es bastante habitual hacer que un hilo se meta en un bucle infinito, realizando una tarea indefinidamente, pero también podemos hacer el ciclo continúe o se pare dependiendo de una variable específica.
    @Override
        public void run() {
            /*aquí va el código que se ejecutará en el hilo*/
            while(seguirHilo){
                System.out.println(cont+" :Hola mundo desde java usando hilos");
                cont++;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    Si queremos que este hilo termine y buscamos en la API de java, vemos que todos los métodos para detener hilos (Thread.destroy()Thread.suspend(), etc) están obsoletos, desaconsejados, etc.
    ¿Cómo terminamos entonces el hilo?
    La forma que habitualmente implemento, es poner una variable booleana que indica si el hilo debe terminarse y usarla en el while.
    @Override
        public void run() {
            /*aquí va el código que se ejecutará en el hilo*/
            while(seguirHilo){
                System.out.println(cont+" :Hola mundo desde java usando hilos");
                cont++;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    De esta forma, para terminar el hilo de forma segura, bastará con llamar al método pararHIlo(false);
    public void pararHIlo(boolean estado){
            seguirHilo=estado;
        }