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:
Felicidades hermano, te sacaste un 100 cn esto
esta muy padre el proyecto, y la implementacion en el applet
felicades nuevamente
y gracias por k me sirvio para entregar un trabajo de ultima hora.
qué pasa con el metodo main?
Como es un entorno gráfico el método main ( o metodo que da inicio a los procesos) es reemplazo por el método que ejecuta la aplicación es decir por un action ( o el action de un botón).
Suerte!
perdon no vi que era un applet
gracias