Simulador de processos

Pessoal preciso desenvolver um software que simule os processos tipo FIFO(First in First out), porem não sei por onde começar e não encontro material de estudo como apostilas ou tutoriais para ter uma ideia, alguem conhece alguma apostila,site, ou videos para me dar uma luz, obrigado!

Como assim um simulador de processos? Você quer implementar um algoritmo de escalonamento? Ou uma estrutura de dados?

1 curtida

Se você quer implementar uma espécie de algoritmo de escalonamento de processos (utilizando threads, no caso), pode utilizar as estruturas de dados já oferecidas pelo pacote de concorrência, java.util.concurrent, em especial algo como as que implementam a interface BlockingQueue.

Você pode fazer assim:

  1. Cria um objeto que implementa BlockingQueue (tem vários prontos, só pesquisar na documentação);
  2. Starta várias threads, e para cada uma delas você passa essa referencia do objeto. Cada thread vai gerar “processos” nessa fila (pode ser só um número dizendo quanto tempo o processo demora), de forma aleatória. É só um loop com um sleep randômico é um insert na “fila de processos”;
  3. Em outra thread, a que simularia o processador, você vai consumir os objetos colocados na BlockingQueue, de forma serial, caracterizando o FIFO.
1 curtida

Obrigado cara , dei uma estudada basica e saiu isso da uma olhada, pretendo melhorar mto ainda esse é só a base de como vai ser.

import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class linkedTest {

public static void main(String[] args) {
    final BlockingQueue<String> queue = new LinkedBlockingQueue<>(1024);
    

    //produtor de processos
    new Thread(new Runnable() {

        public void run() {
            while (true) {
                
                try {
                    String processo = UUID.randomUUID().toString();
                    System.out.printf("[%s] MEMORIA [%s].%n",
                            Thread.currentThread().getName(), processo);
                    
                    queue.put(processo);
                    Thread.sleep(250);
                } catch (Exception e) {
                    System.err.print(e);
                }
            }
           
        }

    }, "Memoria").start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    String processo = queue.take();
                    System.out.printf("[%s] PROCESSANDO [%s].%n",
                            Thread.currentThread().getName(), processo);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }, "Processador").start();
}

}

1 curtida

Foi exatamente isso que eu quis dizer! Dessa forma, você nem precisa esquentar com a sincronização, porque a estrutura de dados faz isso pra ti.

Dá pra tu montar um design de classes muito maneiro com essa estrutura. Existem várias formas de fazer, claro. Vou te dar só uma ideia, você faz como achar melhor!

  1. Cria uma classe chamada Processo. Essa classe vai ter um nome, uma duração e qualquer outro dado pertinente. Faz com que ela seja imutável (declara todas as variáveis como final e não deixa ninguém alterar o que tem ali dentro depois que o objeto é criado);

  2. Cria duas interfaces. Vou inventar os nomes agora, mas você pode criar nomes melhores:

    1. ProvedorDeProcessos: Essa interface tem só um método, algo como:

       public interface ProvedorDeProcessos {
           Processo proximoProcesso();
       }
      
    2. EnfileiradorDeProcessos: Essa interface também só tem um método, tipo assim:

       public interface EnfileiradorDeProcessos {
           void enfileirar(Processo p);
       }
      
  3. Cria mais uma classe chamada de GerenciadorDeProcessos (péssimo nome). Essa classe implementa as duas interfaces que eu comentei anteriormente. Dentro dela, faz assim: tem uma variável do tipo BlockingQueue, e os métodos proximoProcesso e enfileirar, das interfaces implementadas, que não fazem nada alem de delegar a chamada para a BlockingQueue (não tem nada diferente do que você já fez, só organização);

  4. Finalmente, cria mais duas classes, Processador e ProdutorDeProcessos. Essas duas classes vão implementar a interface Runnable, para que você possa passar esses objetos para novas threads. O construtor de Processador recebe um objeto do tipo ProvedorDeProcessos, e o construtor de ProdutorDeProcessos recebe um objeto do tipo EnfileiradorDeProcessos. Talvez haja um pouco de confusão aqui, mas acho que um exemplo de como ficaria o método main vai ajudar a entender.


public static void main(String... args) {
    // Esse é o cara que tem a BlockingQueue internamente, de forma encapsulada.
    // Ninguém precisa saber que é usada uma BlockingQueue.
    // Inclusive, dessa forma, você pode mudar a implentação interna,
    // fazendo você mesmo a sincronização através de locks, caso necessário.
    GerenciadorDeProcessos gerenciador = new GerenciadorDeProcessos();

    Processador processador = new Processador(gerenciador); 
    // por causa do polimorfismo, o processador só vê o método proximoProcesso()

    ProdutorDeProcessos produtorA = new Produtor(gerenciador); 
    // por causa do polimorfismo, o produtor só vê o método enfileirar(Processo);
    ProdutorDeProcessos produtorB = new Produtor(gerenciador);
    ProdutorDeProcessos produtorC = new Produtor(gerenciador);

    // Como ambos Produtor e Processador implementam Runnable, você pode fazer isso:

    newThread(processador).start();
    newThread(produtorA).start();
    newThread(produtorB).start();
    newThread(produtorC).start();
}

No Processador, ao invés de um Thread.sleep() com qualquer número, você pode colocar a thread do produtor para dormir tendo a duração do processo que ele está processando, ficaria uma simulação bem interessante!

Boa sorte :wink:

1 curtida