No es un bug, es una característica no documentada

martes, 27 de octubre de 2015

Procesos y servicios. Hilos. Applets

Un Applet es una aplicación Java que se incrusta en una página HTML, aunque los navegadores, por defecto, no permiten este tipo de programas en las webs porque son una brecha de seguridad.

Estos applets se extienden de la clase Applet, así que la creación de los hilos, en caso de que queramos hacerlo todo en una única clase, habrá que dejarlo a Runnable.

Un ejemplo sería este Applet para crear un reloj:

import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class Reloj extends Applet implements Runnable {

     private Thread hilo = null;    //hilo
     private Font fuente; //Tipo de letra para la hora
     private String horaActual = "";
    
     public void init(){
          fuente = new Font ("Verdana", Font.BOLD, 26);
     }//fin de init
    
     public void start(){
          if(hilo == null){
                hilo = new Thread(this);
                hilo.start();
          }
     }//fin de start
    
     @Override
     public void run() {
          Thread hiloActual = Thread.currentThread();
          while (hilo == hiloActual){
                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
                Calendar cal = Calendar.getInstance();
                horaActual = sdf.format(cal.getTime());
                repaint(); //se actualiza el contenido del Applet
                try {
                     Thread.sleep(1000);
                } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                }
          }
     }//fin de run

     public void paint (Graphics g){
          g.clearRect(1, 1, getSize().width, getSize().height);
          setBackground(Color.yellow);   //Color de fondo
          g.setFont(fuente);
          g.drawString(horaActual, 20, 50);//Muestra la hora
     }//fin de paint
    
     public void stop(){
          hilo=null;
     }
}

O este otro para realizar un contador:

import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ContadorApplet extends Applet implements Runnable, ActionListener {
     private Thread h;
     long CONTADOR = 0;
     private boolean parar;
     private Font fuente;
     private Button b1,b2; //botones del Applet
    
     public void start() {}
    
     public void init() {
    
          setBackground(Color.yellow);//color de fondo
          add(b1=new Button("Iniciar contador"));
          b1.addActionListener(this);
          add(b2=new Button("Parar contador"));   
          b2.addActionListener(this);
          fuente = new Font("Verdana", Font.BOLD, 26);//tipo letra
    
     }
         
    
    
     public void run() {
    
          parar=false;
          Thread hiloActual = Thread.currentThread();
          while (h == hiloActual && !parar) {
                try {
                     Thread.sleep(300);
                } catch (InterruptedException e) {
                     e.printStackTrace();
                }
                repaint();
                CONTADOR++;
          }
     }
    
    
    
     public void paint(Graphics g) {
    
          g.clearRect(0, 0, 400, 400);
          g.setFont(fuente);   //fuente
          g.drawString(Long.toString((long)CONTADOR),80,100);
    
     }
    
    
    
     //para controlar que se pulsan los botones
     public void actionPerformed(ActionEvent e) {
         
          b1.setLabel("Continuar");
          if(e.getSource()==b1) //comienzo
          {
                if(h!=null && h.isAlive()) {
                }    //Si el hilo está corriendo no hago nada,
                else { //lo creo
                     h = new Thread(this);
                     h.start();
                }
          }else if(e.getSource()==b2) //parada
                parar=true;
    
     }//fin de actionPerformed
    
    
    
     public void stop() {
          h = null;
     }
    
    
}//fin applet

Pero no tiene porqué ser así. Partiendo del ejemplo anterior, podemos realizar un applet que separe el hilo en una clase aparte dentro del applet que extienda Thread. El applet que ahora no implementará Runnable, debe quedar así:

public class actividad2_2 extends Applet implements ActionListener {
class HiloContador extends Thread {
//atributos y métodos
. . .
}//fin clase
//atributos y métodos
. . .
}//fin applet

Para hacernos una idea, vamos a crear la misma aplicación de contador que antes pero que lance dos hilos y muestre dos botones para finalizarlos. Algo así




Es decir, definimos en la clase HiloContador un constructor que reciba el valor inicial del contador a partir del cual empezará a contar; y el método getContador() que devuelva el valor actual del contador.

El applet debe crear e iniciar dos hilos de esta clase, cada uno debe empezar con un valor. Mostrará dos botones, uno para detener el primer hilo y el otro el segundo. Para detener los hilos usa el método stop(): hilo.stop() (Veremos más adelante que este método está en desuso y no se debe emplear). Cambiamos también el texto de los botones cuando se pulsen, para que muestre algún mensaje dependiendo del botón pulsado.

El código queda tal que así:

import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AppletContador extends Applet implements ActionListener{

class HiloContador extends Thread{

// Propiedades
long CONTADOR = 0;
boolean parada = false;

// Constructor
public HiloContador(int hilo){
CONTADOR = hilo;
}

// Métodos
public void pararHilo(){
parada = true;
}

public void activarHilo(){
parada = false;
}

public void run(){
while(!parada){
try{
Thread.sleep(1000);
}
catch(InterruptedException e){
e.printStackTrace();
}
CONTADOR++;
repaint();
}

} // fin de clase HiloContador

// Propiedades
private Font fuente;
private Button btn1, btn2;
HiloContador t1, t2;
int a, b;

// Métodos
public void init(){
// Los genero con inicio aleatorio
t1 = new HiloContador((int) (Math.random()*100+1)); 
t2 = new HiloContador((int) (Math.random()*100+1));
setBackground(Color.orange);
fuente = new Font("Verdana", Font.BOLD, 26);
add(btn1 = new Button("Parar contador 1"));
btn1.addActionListener(this);
add(btn2 = new Button("Para contador 2"));
btn2.addActionListener(this);
t1.start();
t2.start();
}


public void paint(Graphics g){
g.clearRect(0, 0, 400, 400); 
g.setFont(fuente); //fuente 
g.drawString("Hilo 1: " + Long.toString((long)t1.CONTADOR),40,100); 
g.drawString("Hilo 2: " + Long.toString((long)t2.CONTADOR),40,150);
//repaint();
}

public void actionPerformed(ActionEvent e) { 
 
if(e.getSource() == btn1) 

if(t1.isAlive()) {
t1.pararHilo();
a = (int) t1.CONTADOR;
btn1.setLabel("Activar contador 1");

else {
t1.activarHilo();
t1 = new HiloContador(a+1);
t1.start();
btn1.setLabel("Parar contador 1");

}else if(e.getSource() == btn2){
if(t2.isAlive()){
t2.pararHilo();
b = (int) t2.CONTADOR;
btn2.setLabel("Activar contador 2");
}
else{
t2.activarHilo();
t2 = new HiloContador(b+1);
t2.start();
btn2.setLabel("Parar contador 2");
}
}
} // Fin actionPerformed
}

0 comentarios:

Publicar un comentario