Lectores y Escritores en Java con Progress Bar

La solución del algoritmo de lectores y escritores en Java será detallada en este Post, donde vemos la interacción semejante al algoritmo de Productor Consumidor, pero con la diferencia que esta vez, los escritores tienen mayor prioridad que los lectores y solo uno a la vez puede acceder al recurso.

Como se imaginarán este es un problema típico de Hilos con Monitores, o más conocidos como Threads and Monitors, donde los hilos acceden continuamente al recurso compartido pero solo uno a la vez.

La solución del problema de Lectores y Escritores en Java o Readers and Writers Threads, se muestra a continuación, es necesario que copien todas las fuentes descritas, y las adapten a su proyecto.


Se que este Post será ayuda, asi que una forma de retribuir esa ayuda, es visitando los Sitios Recomendados que aparecen a la izquierda del post o la publicidad ya que ellos proveen información relacionada al post presente y darán mayor presencia al Blog de su servidor…

Además pueden recomendar este Blog en delicius o cualquier otra red social que encuentre, tambien seria bueno que compartan sus experiencias a través de sus comentarios.

Seguimos:
1er Archivo:La Clase Monitor o Tuberia.java


package gui;

class Tuberia {
private char buffer[] = new char[25];
public int siguiente = 0;
// Flags para saber el estado del buffer
private boolean estaLlena = false;
private boolean estaVacia = true;
public String alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//es el buffer que compartiran
public int max_buffer=25;//maxima cantidad del buffer
private pantalla pan;

private int lectores = 0;
private int lectoresEsperando = 0;
private int escritoresEsperando = 0;
private boolean escribiendo = false;

VariableCondicion okParaLeer = new VariableCondicion();
VariableCondicion okParaEscribir = new VariableCondicion();

public Tuberia(pantalla p){
this.pan = p;//esta es la pantalla
}

public void ComenzarEscritura ( char c , int nombre )throws InterruptedException{

synchronized(this.okParaEscribir){ //acceso a la variable

synchronized(this){ //exclusion mutua en el metodo

if(escribiendo | lectores>0 | siguiente == max_buffer){

escritoresEsperando ++;
this.okParaEscribir.quieroDormir = true;

}else{

escribiendo = true;
this.okParaEscribir.quieroDormir = false;

//ESCIBIMOS ALGO

buffer[siguiente] = c;
this.pan.set_textArea("Escritor "+nombre+"->Escribiendo "+c+" a la tuberia.");
this.pan.set_progreso(siguiente);
// Cambia al siguiente lugar disponible
siguiente++;
// Comprueba si el buffer está lleno
if( siguiente == this.max_buffer){
estaLlena = true;
this.pan.set_textArea("El buffer esta lleno");
}//if
estaVacia = false;

//FIN DE LA ESCRITURA

}//else

}//fin del synch -- Suelto el cerrojo del metodo

if(this.okParaEscribir.quieroDormir){
this.okParaEscribir.wait();
}//if

}//fin del synch

}//fin de la funcion

public void TerminarEscritura(){

synchronized(this.okParaLeer){

synchronized(this.okParaEscribir){

synchronized(this){

if(escritoresEsperando > 0 ){
escritoresEsperando --;
this.okParaEscribir.notify(); //Despertar al primer escritor
}else{
escribiendo = false;
this.okParaLeer.notifyAll(); //Despertar lectores
lectores = lectoresEsperando;
lectoresEsperando = 0;

}//else

}//synch

}//synch

}//synch

}// Fin de la Funcion

public void ComenzarLectura ( int nombre )throws InterruptedException{

synchronized(this.okParaLeer){ //acceso a la variable

synchronized(this){ //exclusion mutua en el metodo

if(escribiendo | escritoresEsperando >0 | siguiente==0 ){

lectoresEsperando ++;
this.okParaLeer.quieroDormir = true;

}else{

lectores ++;
this.okParaLeer.quieroDormir = false;

//LEEMOS ALGO

siguiente--;
this.pan.set_textArea("Lector "+nombre+"->Leyendo "+buffer[siguiente]+" de la Tuberia ");
this.pan.set_progreso(siguiente);
// Comprueba si se retiró la última letra
if( siguiente == 0 ){
estaVacia = true;
this.pan.set_textArea("El buffer esta vacio");
}//if

// El buffer no puede estar lleno, porque acabamos de consumir
estaLlena = false;

//FIN DE LA ESCRITURA

}//else

}//fin del synch -- Suelto el cerrojo del metodo

if(this.okParaLeer.quieroDormir){
this.okParaLeer.wait();
}//if

}//fin del synch

}//fin de la funcion

public void TerminarLectura(){

synchronized(this.okParaEscribir){

synchronized(this){

lectores --;

if(lectores == 0 & escritoresEsperando >0){
escritoresEsperando --;
this.okParaEscribir.notify();

}

}//synch

}//synch

}// Fin de la Funcion

}//clase

2do Archivo:La Clase Escritor.java


package gui;

class Escritor extends Thread {
private Tuberia tuberia;
private pantalla pan;
private int nombre;
private int duerme = 1000;
public Escritor( Tuberia t , pantalla pan, int nombre) {
// Mantiene una copia propia del objeto compartido
tuberia = t;
this.pan = pan;
this.nombre = nombre;

}

public void run() {
char c;

while(true){
c = tuberia.alfabeto.charAt( (int)(Math.random()*26 ) );

try {
// Escribe un registro con lo añadido
tuberia.ComenzarEscritura ( c , nombre);
// Espera un poco antes de añadir más letras

tuberia.TerminarEscritura();
sleep(this.duerme);
} catch( InterruptedException e ) {
;
}
}//fin del while
}//fin del void run

public void set_duerme(int duerme){
this.duerme = duerme;
}//function

}//fin de la clase

3er Archivo:La Clase Lector.java


package gui;

class Lector extends Thread {
private Tuberia tuberia;
private pantalla pan;
private int nombre;
private int duerme= 1000;
public Lector(Tuberia t , pantalla pan, int nombre) {
// Mantiene una copia propia del objeto compartido
tuberia = t;
this.pan = pan;
this.nombre = nombre;
}

public void run() {

while(true ){

try {
// Lee letras de la tubería
tuberia.ComenzarLectura(nombre);
// Espera un poco antes de leer más letras
tuberia.TerminarLectura();
sleep(this.duerme);
} catch( InterruptedException e ) {
;
}
}//fin del while
}//fin de la funcion run

public void set_duerme(int duerme){
this.duerme = duerme;
}//function
}//class

4to Archivo:La Clase VariableCondicion.java


public class VariableCondicion {

public boolean quieroDormir = false;

}

5to Archivo: La Clase Pantalla.java


package gui;

public class pantalla extends java.applet.Applet {

//Vector de Escritores y Lectores
Escritor vEscritor[] = new Escritor[30];
Lector vLector[] = new Lector[30];
Tuberia tuberia;
public int np =2;//numero de Escritores
public int nc =1;//numero de Lectores
public int producido = 0;

public void init() {
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
initComponents();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}

public void set_textArea(String texto){
this.txt_output.setText(this.txt_output.getText()+"\n"+texto);
}//function

public void set_progreso(int prog){
this.progreso.setValue(prog);
}//function

/** This method is called from within the init() method to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {

txt_nc = new javax.swing.JTextField();
btn_correr = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
txt_np = new javax.swing.JTextField();
jLabel3 = new javax.swing.JLabel();
txt_vc = new javax.swing.JTextField();
txt_vp = new javax.swing.JTextField();
jLayeredPane1 = new javax.swing.JLayeredPane();
jLayeredPane2 = new javax.swing.JLayeredPane();
jLabel4 = new javax.swing.JLabel();
txt_output = new java.awt.TextArea();
btn_velocidad = new javax.swing.JButton();
jLabel6 = new javax.swing.JLabel();
progreso = new javax.swing.JProgressBar();

setBackground(new java.awt.Color(255, 255, 204));
setLayout(null);

txt_nc.setName("txt_nc"); // NOI18N
txt_nc.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txt_ncActionPerformed(evt);
}
});
add(txt_nc);
txt_nc.setBounds(130, 50, 50, 20);

btn_correr.setText("Correr");
btn_correr.setName("bnt_correr"); // NOI18N
btn_correr.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btn_correrActionPerformed(evt);
}
});
add(btn_correr);
btn_correr.setBounds(210, 50, 120, 50);

jLabel1.setText("Lectores");
add(jLabel1);
jLabel1.setBounds(10, 50, 130, 20);

jLabel2.setText("Escritores");
add(jLabel2);
jLabel2.setBounds(10, 90, 140, 20);

txt_np.setName("txt_np"); // NOI18N
txt_np.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txt_npActionPerformed(evt);
}
});
add(txt_np);
txt_np.setBounds(130, 90, 50, 20);

jLabel3.setText("Velocidad");
add(jLabel3);
jLabel3.setBounds(350, 30, 80, 14);

txt_vc.setName("txt_vc"); // NOI18N
add(txt_vc);
txt_vc.setBounds(350, 50, 50, 20);

txt_vp.setName("txt_vp"); // NOI18N
add(txt_vp);
txt_vp.setBounds(350, 80, 50, 20);
add(jLayeredPane1);
jLayeredPane1.setBounds(330, 50, 0, 0);
add(jLayeredPane2);
jLayeredPane2.setBounds(300, 70, 0, 0);

jLabel4.setFont(new java.awt.Font("Verdana", 1, 14));
jLabel4.setForeground(new java.awt.Color(51, 51, 51));
jLabel4.setText("Lectores Escritores con Buffer Limitado");
add(jLabel4);
jLabel4.setBounds(10, 10, 340, 15);

txt_output.setFont(new java.awt.Font("Verdana Ref", 0, 12));
add(txt_output);
txt_output.setBounds(20, 150, 570, 310);

btn_velocidad.setText("Fijar velocidad");
btn_velocidad.setName("bnt_correr"); // NOI18N
btn_velocidad.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btn_velocidadActionPerformed(evt);
}
});
add(btn_velocidad);
btn_velocidad.setBounds(420, 50, 160, 50);

jLabel6.setText("Valor del Buffer = 25 caracteres");
add(jLabel6);
jLabel6.setBounds(10, 120, 340, 14);

progreso.setMaximum(24);
progreso.setName("progreso"); // NOI18N
add(progreso);
progreso.setBounds(20, 470, 570, 50);
}// </editor-fold>//GEN-END:initComponents

private void btn_velocidadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_velocidadActionPerformed
//fijamos los valores de las velocidades
int vc , vp ;

if(this.txt_vc.getText()==""){
vc = 500;
}else{
vc = Integer.parseInt(this.txt_vc.getText());
}
if(this.txt_vp.getText()==""){
vp = 500;
}else{
vp = Integer.parseInt(this.txt_vp.getText());
}

for(int i = 0; i<Integer.parseInt(this.txt_np.getText()); i++){
vEscritor[i].set_duerme(vp);
}//for
for(int i = 0; i<Integer.parseInt(this.txt_nc.getText()); i++){
vLector[i].set_duerme(vc);
}//for
}//GEN-LAST:event_btn_velocidadActionPerformed

private void btn_correrActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btn_correrActionPerformed

tuberia = new Tuberia(this);

//controlamos la cantidad de escritores y lectores
if(this.txt_np.getText()==""){
np = 0;
}else{
np = Integer.parseInt(this.txt_np.getText());
}
if(this.txt_nc.getText()==""){
nc = 0;
}else{
nc = Integer.parseInt(this.txt_nc.getText());
}

for(int i = 0; i<np; i++){
vEscritor[i] = new Escritor(tuberia,this,i+1);
vEscritor[i].start();
}//for

for(int i = 0; i< nc; i++){
vLector[i] = new Lector(tuberia,this,i+1);
vLector[i].start();
}//for
}//GEN-LAST:event_btn_correrActionPerformed

private void txt_npActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txt_npActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txt_npActionPerformed

private void txt_ncActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txt_ncActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txt_ncActionPerformed

// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btn_correr;
private javax.swing.JButton btn_velocidad;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel6;
private javax.swing.JLayeredPane jLayeredPane1;
private javax.swing.JLayeredPane jLayeredPane2;
private javax.swing.JProgressBar progreso;
private javax.swing.JTextField txt_nc;
private javax.swing.JTextField txt_np;
private java.awt.TextArea txt_output;
private javax.swing.JTextField txt_vc;
private javax.swing.JTextField txt_vp;
// End of variables declaration//GEN-END:variables

}

El Problema ha sido resuelto con IDE Netbeans 6.0 , pero puede funcionar con cualquier IDE de Java, les dejo las fuentes para que lo prueben:

Lectores y Escritores en Java con Progress Bar

This entry was posted on Monday, March 3rd, 2008 at 1:01 am and is filed under Java, Soluciones. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply