Meu primeiro post no Estação ZN!
Numa manhã sem muito trabalho escrevi um programa em JAVA para ilustrar alguns recursos. Tem threads concorrentes, swing, observable para conectar objetos a GUI, herança, interface e mais algumas coisas.
O programa ilustra a concorrência de dois objetos tentando se conectar para formar uma parceria e se reproduzir em um novo objeto que vai continuar com esse ciclo.
Acredito que esse programa possa ajudar a quem está começando ou quem quer ver um exemplo dos recursos que citei.
Como funciona:
Existe uma classe Elemento que define o objeto principal e que será herdada por Macho e Fêmea. Os Objetos da classe Macho e Fêmea são associados a um objeto da classe Ambiente. A classe Ambiente define o ambiente onde os objetos viverão. A classe Elemento implementa Runnable e no método run executa o código necessário para dar vida aos objetos.
Abaixo um diagrama simplificado dessas classes.
A classe Main é um JFrame que exibe os objetos criados como JButtons. A classe Main possui um método simular que inicia a simulação.
A seguir as principais classes do programa.
Classe: Elemento
package simulador;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
public abstract class Elemento implements Runnable {
private static int contador = 0;
private int id;
private Elemento mae;
private Elemento pai;
private long nascimento;
private long morte;
private int folego = 3 * 1000;
private int idadeMaxima = 2 * 60 * 1000;
private boolean running = true;
private boolean vivo = true;
private boolean ocupado;
protected Ambiente ambiente;
protected Elemento parceiro;
private ArrayListmemoria = new ArrayList ();
private ArrayListobservadoresVida = new ArrayList ();
private ArrayListobservadoresMorte = new ArrayList ();
private ArrayListobservadoresParceria = new ArrayList ();
public Elemento(Ambiente ambiente) {
id = contador++;
setAmbiente(ambiente);
}
public int getFolego() {
return folego;
}
public void setFolego(int folego) {
this.folego = folego;
}
public int getIdadeMaxima() {
return idadeMaxima;
}
public void setIdadeMaxima(int idadeMaxima) {
this.idadeMaxima = idadeMaxima;
}
public Elemento getMae() {
return mae;
}
public void setMae(Elemento mae) {
this.mae = mae;
}
public Elemento getPai() {
return pai;
}
public void setPai(Elemento pai) {
this.pai = pai;
}
public int getId() {
return id;
}
public ArrayListgetMemoria() {
return memoria;
}
protected void memorizar(String s) {
memoria.add(id + ": " + new Date() + ": " + s);
}
public void setAmbiente(Ambiente ambiente) {
this.ambiente = ambiente;
}
public void setRunning(boolean running) {
this.running = running;
}
public boolean isRunning() {
return running && ambiente.isRunnig() && !expirou();
}
public boolean expirou() {
long idade = System.currentTimeMillis() - nascimento;
return idade > idadeMaxima;
}
public long idadeMorte() {
long idade = morte - nascimento;
return idade;
}
public boolean isVivo() {
return vivo;
}
public Elemento getParceiro(){
return parceiro;
}
private synchronized boolean ocupar() {
if (!ocupado) {
ocupado = true;
return true;
} else {
return false;
}
}
private void liberar() {
ocupado = false;
}
private boolean aceitar(Elemento outro) {
if (solteiro() && desejo()) {
String s1 = "Aceitei o convite para ser parceiro do " + outro.id + ".";
notificarEncontrarParceiro(s1);
parceiro = outro;
outro.parceiro = this;
return true;
} else {
String s2 = "N?o aceitei o convite para ser parceiro do " + outro.id + ".";
notificarEncontrarParceiro(s2);
return false;
}
}
private void encontrarParceiro() {
if (ocupar()) {
Random rand = new Random();
int quantidadeDeElementos = candidatos().size();
int aleatorio = rand.nextInt(quantidadeDeElementos);
Elemento outro = candidatos().get(aleatorio);
if (!equals(outro)) {
String s1 = "Escolhi o " + outro.id + " para ser parceiro.";
notificarEncontrarParceiro(s1);
if (!outro.vivo) {
String s2 = "O " + outro.id + " estava morto.";
notificarEncontrarParceiro(s2);
} else if (outro.ocupar()) {
String s3 = "Convidando o " + outro.id + " para ser parceiro.";
notificarEncontrarParceiro(s3);
if (outro.aceitar(this)) {
String s4 = "O " + outro.id + " aceitou ser parceiro.";
notificarEncontrarParceiro(s4);
} else {
String s5 = "O " + outro.id + " n?o aceitou ser parceiro.";
notificarEncontrarParceiro(s5);
}
outro.liberar();
} else {
String s6 = "O " + outro.id + " estava ocupado.";
notificarEncontrarParceiro(s6);
}
}
liberar();
}
}
protected abstract Elemento reproduzir();
protected abstract Listcandidatos();
protected boolean desejo() {
Random rand = new Random();
int aleatorio = rand.nextInt(2);
if (aleatorio == 1) {
return true;
} else {
return false;
}
}
public boolean equals(Object o) {
Elemento outro = (Elemento) o;
if (outro == this) {
return true;
}
if (outro.id == id) {
return true;
}
return false;
}
public boolean solteiro() {
return parceiro == null;
}
public void run() {
notificarNascimento();
nascimento = System.currentTimeMillis();
while (isRunning()) {
if (solteiro()) {
if (desejo()) {
encontrarParceiro();
}
} else { // Possui um parceiro, pode se reproduzir.
if (desejo() && parceiro.isVivo() && parceiro.desejo()) {
Elemento novo = reproduzir();
if (novo != null) {
try {
new Thread(novo).start();
} catch (OutOfMemoryError e) {
ambiente.setRunning(false);
throw e;
}
}
}
}
if (isRunning()) {
try {
Thread.sleep(folego);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
morte = System.currentTimeMillis();
vivo = false;
notificarMorte();
}
public ArrayListgetObservadoresVida() {
return observadoresVida;
}
public ArrayListgetObservadoresMorte() {
return observadoresMorte;
}
public ArrayListgetObservadoresParceria() {
return observadoresParceria;
}
public void addObservadoresVida(Ouvinte o) {
observadoresVida.add(o);
}
public void addObservadoresMorte(Ouvinte o) {
observadoresMorte.add(o);
}
public void addObservadoresParceria(Ouvinte o) {
observadoresParceria.add(o);
}
private void notificarNascimento() {
memorizar("Nasci.");
for (Ouvinte e : observadoresVida) {
e.atualizar(this, "Nasci.");
}
}
private void notificarMorte() {
memorizar("Morri.");
for (Ouvinte e : observadoresMorte) {
e.atualizar(this, "Morri.");
}
}
private void notificarEncontrarParceiro(String s) {
memorizar(s);
for (Ouvinte e : observadoresParceria) {
e.atualizar(this, s);
}
}
protected void notificarNascimento(Elemento e, String s) {
memorizar(s);
for (OuvinteNascimento o : ambiente.getObservadoresNascimento()) {
o.atualizar(this, e, s);
}
}
}
Classe: Macho
package simulador;
import java.util.List;
public class Macho extends Elemento {
public Macho(Ambiente ambiente){
super(ambiente);
ambiente.getElementosMachos().add(this);
ambiente.getElementos().add(this);
}
protected Elemento reproduzir() {
return null;
}
protected Listcandidatos() {
return ambiente.getElementosFemeas();
}
}
Classe: Femea
package simulador;
import java.util.List;
public class Femea extends Elemento {
public Femea(Ambiente ambiente) {
super(ambiente);
ambiente.getElementosFemeas().add(this);
ambiente.getElementos().add(this);
}
protected Listcandidatos() {
return ambiente.getElementosMachos();
}
protected Elemento reproduzir() {
Elemento e;
if (desejo()) {
e = new Femea(ambiente);
notificarNascimento(e, "Pari a femea " + e.getId());
} else {
e = new Macho(ambiente);
notificarNascimento(e, "Pari o macho " + e.getId());
}
e.setMae(this);
e.setPai(parceiro);
return e;
}
}
Classe: Main
package simulador;
public class Main extends javax.swing.JFrame {
public Main() {
initComponents();
}
/** 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")
//
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Simulador");
getContentPane().setLayout(new java.awt.FlowLayout());
pack();
}//
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
final Main f = new Main();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
f.setVisible(true);
}
});
f.simular();
}
Detalhe detalhe;
public Detalhe detalhe() {
if (detalhe == null) {
detalhe = new Detalhe();
}
return detalhe;
}
public void print(final Elemento e) {
javax.swing.JButton elementoGrafico = new javax.swing.JButton();
elementoGrafico.setText("" + e.getId());
getContentPane().add(elementoGrafico);
elementoGrafico.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
detalhe().setDetalhe(e.getMemoria());
detalhe().setVisible(true);
}
});
pack();
}
public void simular() {
int TEMPO_DE_VIDA = 2 * 60 * 1000;
Ambiente ambiente = new Ambiente();
ambiente.addObservadoresNascimento(new OuvinteNascimento() {
public void atualizar(Elemento mae, Elemento filho, String s) {
print(filho);
}
});
Elemento m = new Macho(ambiente);
print(m);
new Thread(m).start();
Elemento f = new Femea(ambiente);
print(f);
new Thread(f).start();
try {
Thread.sleep(TEMPO_DE_VIDA);
} catch (InterruptedException e) {
e.printStackTrace();
}
ambiente.setRunning(false);
while (ambiente.vivo()) {
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
System.out.println("Fim.");
}
// Variables declaration - do not modify
// End of variables declaration
}
Não está comentado, mas começando da classe Main ninguém se perde. O programa vem como um projeto Netbeans, mas vai rodar fácil no Eclipse.
Vou continuar melhorando o programa, aceito comentários, sugestões, melhorias e correções!
Obs: A tela de detalhe não se atualiza sozinha.
Abraços, Rodrigo Alencar.
Oi, encontrei esta pagina por acaso. Estou agora me iniciando no java e este programa excelente fez-me lembrar algo parecido que fiz na universidade, mas em linguagem c. Estou a tentar perceber o codigo do teu programa, mas nao percebo a forma como usas o ciclo "for". Nunca antes tinha visto e ja tive a procurar na net e nao encontro uma explicação para usar o "for" da forma "for ( : )", como em "for (Ouvinte e : observadoresParceria)" Se pudesses me dar uma pequena explicação, agradecia. Obrigado
ResponderExcluir