Quantcast
Channel: Programação - GUJ
Viewing all articles
Browse latest Browse all 33096

Sincronizar acesso das threads

$
0
0

@filipecampos escreveu:

Existem três threads clientes que enviam requisições para cada Objeto Servidor.
Cada Objeto Servidor tem três threads receptoras, cada uma responsável por atender a um cliente distinto. Observem que cada requisição é enviada para todos os três Objetos Servidores através das suas respectivas threads. Esse envio é feito através de um Pipe distinto, não compartilhado. Cada Objeto Servidor possui três métodos: depositar(double valor), retirar(double valor) e aplicarCorrecao(int percentagem), este último faz uma correção monetária sobre o valor
total da conta. Esses métodos são invocados, de forma concorrente, por cada thread no
Objeto Servidor i.

O saldo final em cada servidor devem ser iguais e o valor do saldo estão com uma diferença pequena, problema com os piped, as vezes a Thread de deposito realizar o deposto com o valor do saque e vice versa

Cliente Abstrato

package br.com.cliente;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PipedOutputStream;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Classe responsavel por enviar requisições ao servidor
 *
 * @author Filipe
 */
public abstract class AbstractClient extends Thread {

    //Escritor para servidor 1
    protected DataOutputStream out1;
    //Escritor para servidor 2
    protected DataOutputStream out2;
    //Escritor para servidor 3
    protected DataOutputStream out3;
    protected Random random;
    protected float value;

    public AbstractClient(PipedOutputStream pOut1, PipedOutputStream pOut2, PipedOutputStream pOut3) {
        this.random = new Random();
        this.out1 = new DataOutputStream(pOut1);
        this.out2 = new DataOutputStream(pOut2);
        this.out3 = new DataOutputStream(pOut3);
    }

    /**
     * Seta o valor da acao a ser escrita
     */
    protected abstract void write();

    @Override
    public void run() {

        try {
            for (int i = 0; i < 9; i++) {

                this.write(out1);

                this.write(out2);

                this.write(out3);

            }
            //feche os pipeds
            out1.close();
            out2.close();
            out3.close();

        } catch (IOException ex) {
            Logger.getLogger(AbstractClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    protected void write(DataOutputStream out) throws IOException {

        //acao do cliente
        write();

        //cliente dispara acao
        out.writeFloat(value);

        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(AbstractClient.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Enumerador para indicar qual o servidor deve-se enviar a informação
     
    enum Operacao {

        Server1(1), Server2(2), Server3(3);

        public final int value;

        Operacao(int value) {

            this.value = value;
        }

        public static Operacao fromInteger(int x) {
            switch (x) {
                case 1:
                    return Server1;
                case 2:
                    return Server2;
                default:
                    return Server3;
            }
        }
    }*/

}

Cliente Deposito

package br.com.cliente;

import br.com.server.Server;
import java.io.PipedOutputStream;

/**
 * Thread para deposito
 *
 * @author Filipe
 */
public class ClientDeposito extends AbstractClient {

    public ClientDeposito(PipedOutputStream pOut1, PipedOutputStream pOut2, PipedOutputStream pOut3) {
        super(pOut1, pOut2, pOut3);

    }

    @Override
    protected void write() {
        this.value = Server.DEPOSITO;
    }

}

Cliente Correção

package br.com.cliente;

import br.com.server.Server;
import java.io.PipedOutputStream;

/**
 * Thread para Correcao
 *
 * @author Filipe
 */
public class ClientCorrecao extends AbstractClient {

    public ClientCorrecao(PipedOutputStream pOut1, PipedOutputStream pOut2, PipedOutputStream pOut3) {
        super(pOut1, pOut2, pOut3);
    }

    @Override
    protected void write() {

        this.value = Server.CORRECAO;
    }
}

Cliente Saque

package br.com.cliente;

import br.com.server.Server;
import java.io.PipedOutputStream;

/**
 * Thread para saque
 *
 * @author Filipe
 */
public class ClientSaque extends AbstractClient {

    public ClientSaque(PipedOutputStream pOut1, PipedOutputStream pOut2, PipedOutputStream pOut3) {
        super(pOut1, pOut2, pOut3);
    }

    @Override
    protected void write() {
        this.value = Server.SAQUE;
    }
}

Receptor abstrato

package br.com.receptor;

import br.com.server.Server;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Essa classe sera responsavel por enviar a informaçao ao servidor
 *
 * @author Filipe
 */
public abstract class AbstractReceptor extends Thread {

    //Leitor
    protected DataInputStream dIn;
    protected final Server server;

    public AbstractReceptor(PipedInputStream pis, Server server) {
        this.dIn = new DataInputStream(pis);
        this.server = server;
    }

    //Saque deposito ou correcao
    public abstract void action(float value);

    @Override
    public void run() {

        for (int i = 0; i < 9; i++) {
            try {

                //System.out.println("Aguardando ...");
                //blocante
                float valor = dIn.readFloat();

                //acao do receptor
                action(valor);

            } catch (IOException ex) {
                //if (!ex.getMessage().equals("Pipe closed")) {
                Logger.getLogger(AbstractReceptor.class.getName()).log(Level.SEVERE, null, ex);
            }

          
        }
    }
}

Receptor Deposito

package br.com.receptor;

import java.io.PipedInputStream;

import br.com.server.Server;

/**
 * Repassa o deposito pro valor pro servidor
 *
 */
public class ReceptorDeposito extends AbstractReceptor {

    public ReceptorDeposito(PipedInputStream pis, Server server) {
        super(pis, server);
    }

    @Override
    public void action(float value) {

        System.out.println("Transferindo deposito: " + value);
        if (server != null) {
            this.server.depositar();
        }
    }
}

Receptor Saque

package br.com.receptor;

import java.io.PipedInputStream;

import br.com.server.Server;

public class ReceptorSaque extends AbstractReceptor {

    public ReceptorSaque(PipedInputStream pis, Server server) {
        super(pis, server);
    }

    @Override
    public void action(float value) {

        System.out.println("Sacando: " + value);
        if (server != null) {
            this.server.sacar();
        }

    }
}

Receptor Correção

package br.com.receptor;

import java.io.PipedInputStream;
import br.com.server.Server;

public class ReceptorCorrecao extends AbstractReceptor {

    public ReceptorCorrecao(PipedInputStream pis, Server server) {
        super(pis, server);
    }

    @Override
    public void action(float value) {

        if (server != null) {
            System.out.println("Aplicando correção: " + value);
            this.server.correcao();
        }
    }
}

Servidor

package br.com.server;

import br.com.receptor.ReceptorCorrecao;
import br.com.receptor.ReceptorDeposito;
import br.com.receptor.ReceptorSaque;
import java.io.PipedInputStream;

public class Server extends Thread {

    /**
     * Identificado para o servidor
     */
    private static int ID = 1;

    /**
     * Salvo sera acessado simultaneamente entao preciso ler da memoria
     * principal
     */
    private final int id;
    private volatile float saldo;
    private ReceptorDeposito rdeposito;
    private ReceptorSaque rsaque;
    private ReceptorCorrecao rcorrecao;

    public static final float SAQUE = 3;
    public static final float DEPOSITO = 10;
    public static final float CORRECAO = 0.1f;

    public Server() {
        this.saldo = 10;
        this.id = ID;
        ID++;
    }

    public Server(float saldo, PipedInputStream p1, PipedInputStream p2, PipedInputStream p3) {
        this.saldo = saldo;
        this.rdeposito = new ReceptorDeposito(p1, this);
        this.rsaque = new ReceptorSaque(p2, this);
        this.rcorrecao = new ReceptorCorrecao(p3, this);

        this.id = ID;
        ID++;

    }

    public Server(PipedInputStream p1, PipedInputStream p2, PipedInputStream p3) {

        this(100, p1, p2, p3);
    }

    @Override
    public void run() {

        this.rdeposito.start();
        this.rsaque.start();
        this.rcorrecao.start();

    }

    public synchronized void depositar() {

        System.out.println("Depositado: " + DEPOSITO + " no Servidor: " + id);
        this.saldo += DEPOSITO;

    }

    public synchronized void sacar() {
        System.out.println("Sacado: " + SAQUE + " no Servidor: " + id);
        this.saldo -= SAQUE;
    }

    public synchronized void correcao() {
        System.out.println("Correção aplicada: " + CORRECAO + " no Servidor: " + id);
        this.saldo = saldo + (saldo * CORRECAO);
    }

    public float getSaldo() {
        return saldo;
    }

    public void setSaldo(float saldo) {
        this.saldo = saldo;
    }

    public boolean isAllAlive() {

        return (rdeposito.isAlive() 
                || rsaque.isAlive()
                || rcorrecao.isAlive());
    }

    @Override
    public String toString() {
        return "Server: " + id + " => Saldo: " + saldo;
    }

}

Controller

package br.com.server;

import br.com.cliente.ClientCorrecao;
import br.com.cliente.ClientDeposito;
import br.com.cliente.ClientSaque;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * Classe que controla sincronismo com todos so servidores
 *
 * @author Filipe
 */
public class Controller {

    private final List<Server> servers;
    private boolean open;

    public Controller() {
        this.servers = new ArrayList<>();
    }

    public void runServer() {

        init();

        for (Server s : servers) {

            while (s.isAllAlive()) {
                //espera
            }
        }
        System.out.println("SALDO FINAL");
        for (Server s : servers) {
            System.out.println(s);
        }

    }

    /**
     * Cria os piped out e in
     */
    private void init() {

        try {
            //criando mensageiro para cliente enviar ao receptor
            //criando canal de comunicao para receptor
            //Server 1
            PipedOutputStream s1out1 = new PipedOutputStream();
            PipedInputStream s1in1 = new PipedInputStream(s1out1);
            PipedOutputStream s1out2 = new PipedOutputStream();
            PipedInputStream s1in2 = new PipedInputStream(s1out2);
            PipedOutputStream s1out3 = new PipedOutputStream();
            PipedInputStream s1in3 = new PipedInputStream(s1out3);
            //Server 2
            PipedOutputStream s2out1 = new PipedOutputStream();
            PipedInputStream s2in1 = new PipedInputStream(s2out1);
            PipedOutputStream s2out2 = new PipedOutputStream();
            PipedInputStream s2in2 = new PipedInputStream(s2out2);
            PipedOutputStream s2out3 = new PipedOutputStream();
            PipedInputStream s2in3 = new PipedInputStream(s2out3);
            //Server 3
            PipedOutputStream s3out1 = new PipedOutputStream();
            PipedInputStream s3in1 = new PipedInputStream(s3out1);
            PipedOutputStream s3out2 = new PipedOutputStream();
            PipedInputStream s3in2 = new PipedInputStream(s3out2);
            PipedOutputStream s3out3 = new PipedOutputStream();
            PipedInputStream s3in3 = new PipedInputStream(s3out3);

            //cria o servidor com 3 receptores
            //inicializa os receptores
            Server server1 = new Server(100, s1in1, s1in2, s1in3);
            this.servers.add(server1);

            Server server2 = new Server(100, s2in1, s2in2, s2in3);
            this.servers.add(server2);

            Server server3 = new Server(100, s3in1, s3in2, s3in3);
            this.servers.add(server3);

            //clientes
            new ClientDeposito(s1out1, s1out2, s1out3).start();
            server1.start();

            new ClientSaque(s2out1, s2out2, s2out3).start();
            server2.start();

            new ClientCorrecao(s3out1, s3out2, s3out3).start();
            server3.start();

        } catch (IOException ex) {
            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean status) {
        this.open = status;
    }

}

Mensagens: 1

Participantes: 1

Ler tópico completo


Viewing all articles
Browse latest Browse all 33096


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>