Thread - Alguém consegue me dizer porque não executa a Thread?

Pessoal, já passa a instância da Thread e o método start até dentro do construtor da Classe Impressora, mas não funciona.

Por favor, alguém consegue me dizer porque não executa a thread? O código não dá nenhum erro.

ESSA É A CLASSE MAIN:

import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import tadeu.fila.labs.Documentos;

public class Arquivo {

public static void main(String[] args) {

	Scanner scan = new Scanner(System.in);

	Queue<Documentos> filaDoc = new LinkedList<>();

	Impressora print = new Impressora(filaDoc);
	Thread t = new Thread(print);
	t.start();


	//RESOLVER PROBLEMA DE LOOP INFINITO SE DIGITAR LETRAS AO INVES DE NÚMEROS
	menu(scan, filaDoc);

}

public static void adicionarDocumento(Scanner scan, Queue filaDoc) {

	System.out.println("Digite o nome do documento:");
	String nomeDoc = scan.next();

	System.out.println("Digite a quantidade de páginas:");
	int qtdPaginas = scan.nextInt();

	Documentos doc = new Documentos(nomeDoc, qtdPaginas);

	synchronized(filaDoc) {
		filaDoc.add(doc);
	}
	System.out.println("Documento adicionado com sucesso!");
}

public static void menu(Scanner scan, Queue filaDoc) {

	boolean menuAtivo = true;
	int opcaoMenu = 0;
	while (menuAtivo) {
		System.out.println("1 - Adicionar documentos" + "\n" + "2 - Visualizar fila de impressão" + "\n" + "3 - Sair do Menu" );
		try {
			opcaoMenu = scan.nextInt();
		}
		catch(InputMismatchException e) {
			System.out.println("Digite apenas o número da opção desejada!");
		}
		menuAtivo = executarOpcao(opcaoMenu, filaDoc, scan, menuAtivo);
	}
}

public static boolean executarOpcao(int opcaoMenu, Queue filaDoc, Scanner scan, boolean menuAtivo) {

	synchronized(filaDoc) {
		switch (opcaoMenu) {

		case 1:
			adicionarDocumento(scan, filaDoc);
			break;
		case 2:
			System.out.println(filaDoc.toString());
			break;
		case 3:
			return menuAtivo = false;
		default:
			break;
		}
		return menuAtivo = true;
	}
}

}

ESSA É A CLASSE QUE CONTÉM O MÉTODO RUN.

import java.util.Queue;

public class Impressora implements Runnable{

private Queue<Documentos> doc;

public Impressora(Queue<Documentos> doc) {
	this.doc = doc;
}

public void run() {

	while (!doc.isEmpty()) {
		impressaoDocumento();
	}
}

public synchronized void impressaoDocumento() {
	
	int tamanhoDoc = doc.peek().getQtdPaginas();
	String nomeDoc = doc.peek().getNome();
	
	System.out.println("Iniciando impressão do documento: " + nomeDoc);
	
	for (int i = 0; i < tamanhoDoc; i++) {
		System.out.println("Documento: " + nomeDoc);
		System.out.println("Imprimindo página: " + i + " de " + tamanhoDoc);
	}
	System.out.println(doc.peek() + " foi impresso com sucesso!");
	doc.poll();
}

}

ESSA É A CLASSE DO TIPO DOCUMENTO

import java.util.Queue;

public class Impressora implements Runnable{

private Queue<Documentos> doc;

public Impressora(Queue<Documentos> doc) {
	this.doc = doc;
}

public void run() {

	while (!doc.isEmpty()) {
		impressaoDocumento();
	}
}

public synchronized void impressaoDocumento() {
	
	int tamanhoDoc = doc.peek().getQtdPaginas();
	String nomeDoc = doc.peek().getNome();
	
	System.out.println("Iniciando impressão do documento: " + nomeDoc);
	
	for (int i = 0; i < tamanhoDoc; i++) {
		System.out.println("Documento: " + nomeDoc);
		System.out.println("Imprimindo página: " + i + " de " + tamanhoDoc);
	}
	System.out.println(doc.peek() + " foi impresso com sucesso!");
	doc.poll();
}

}

Porque dizes que não executa?
Simplesmente executa e termina imediatamente porque a tua lista é vazia, logo não vai sequer entrar no while.

1 curtida

Eu achei que ela iria executar e dormir, mas quando adicionasse pelo menu, ela iria executar pois não seria mais vazia.

Tentei fazer umas alterações, depois que vi que realmente tava iniciando e terminando imediatamente.
Deu uns erros, li a documentação e por fim parei pra pensar um pouco e fiz umas alterações que deu certo.

Se você “pmlm” ou outra pessoa poder me ajudar com mais uma coisa agradeço!

Eu entendi a idéia da thread, mas onde colocar cada código, tipo, wait(), notify() me confundi um pouco. Então fiz esse código pra testar, consegui entender o que fiz, mas o SYNCHRONIZED, por exemplo, não sei se era necessário da forma que fiz, se puderem me apontar no código o que é desnecessário me ajudaria muito!

Por fim, assim ficou o código final:

public class Documentos {

private String nome;
private int qtdPaginas;
private boolean documentoImpresso;

public Documentos(String nome, int qtdPaginas) {
	this.nome = nome;
	this.qtdPaginas = qtdPaginas;
	this.documentoImpresso = false;	}

public String getNome() {
	return this.nome;
}

public int getQtdPaginas() {
	return this.qtdPaginas;
}

@Override
public String toString() {
	return "Documento: " + nome + ", Quant. Páginas: " + qtdPaginas + "\n" ;
}

}

import java.util.Queue;

public class Impressora implements Runnable{

private Queue<Documentos> doc;

public Impressora(Queue<Documentos> doc) {
	this.doc = doc;
	Thread t = new Thread(this);
	t.start();
}

public void run() {
	
	boolean rodarThread = true;
	while (rodarThread) {
		
		if (doc.isEmpty()) {
			try {
			Thread.sleep(10000);
			}
			catch(InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			impressaoDocumento();
		}
	}
}

public synchronized void impressaoDocumento() {
	
	int tamanhoDoc = doc.peek().getQtdPaginas();
	String nomeDoc = doc.peek().getNome();
	
	System.out.println("Iniciando impressão do documento: " + nomeDoc);
	
	for (int i = 0; i < tamanhoDoc; i++) {
		System.out.println("Documento: " + nomeDoc);
		System.out.println("Imprimindo página: " + i + " de " + tamanhoDoc);
	}
	System.out.println(doc.peek() + " foi impresso com sucesso!");
	doc.poll();
}

}

import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import tadeu.fila.labs.Documentos;

public class Arquivo {

public static void main(String[] args) {

	Scanner scan = new Scanner(System.in);

	Queue<Documentos> filaDoc = new LinkedList<>();

	Impressora print = new Impressora(filaDoc);

	//RESOLVER PROBLEMA DE LOOP INFINITO SE DIGITAR LETRAS AO INVES DE NÚMEROS
	menu(scan, filaDoc);

}

public static void adicionarDocumento(Scanner scan, Queue filaDoc) {

	System.out.println("Digite o nome do documento:");
	String nomeDoc = scan.next();

	System.out.println("Digite a quantidade de páginas:");
	int qtdPaginas = scan.nextInt();

	Documentos doc = new Documentos(nomeDoc, qtdPaginas);

	synchronized(filaDoc) {
		filaDoc.add(doc);
	}
	System.out.println("Documento adicionado com sucesso!");
}

public static void menu(Scanner scan, Queue filaDoc) {

	boolean menuAtivo = true;
	int opcaoMenu = 0;
	while (menuAtivo) {
		System.out.println("1 - Adicionar documentos" + "\n" + "2 - Visualizar fila de impressão" + "\n" + "3 - Sair do Menu" );
		try {
			opcaoMenu = scan.nextInt();
		}
		catch(InputMismatchException e) {
			System.out.println("Digite apenas o número da opção desejada!");
		}
		menuAtivo = executarOpcao(opcaoMenu, filaDoc, scan, menuAtivo);
	}
}

public static boolean executarOpcao(int opcaoMenu, Queue filaDoc, Scanner scan, boolean menuAtivo) {

	synchronized(filaDoc) {
		switch (opcaoMenu) {

		case 1:
			adicionarDocumento(scan, filaDoc);
			break;
		case 2:
			System.out.println(filaDoc.toString());
			break;
		case 3:
			return menuAtivo = false;
		default:
			break;
		}
		return menuAtivo = true;
	}
}

}

Em vez de usar uma LinkedList, podes usar uma implementação de BlockingQueue, como por exemplo LinkedBlockingQueue. Desta forma, já tens uma estrutura que suporta concorrência e podes ir verificando se existem elementos com o poll, sem teres sleeps no código:

public void run() {

    boolean rodarThread = true;
    while (rodarThread) {  // rodarThread vai ser sempre true pq foi inicializada na linha anterior
        Documentos documento = doc.poll(1, TimeUnit.SECONDS);
        if (documento != null) { // a cada um segundo vai devolver null se não existir um novo documento
            impressaoDocumento(documento); //documento é passado como parametro, uma vez que já foi retirado da lista
        }
    }
}

Em relação ao que te aponto acima de rodarThread ser sempre true, deves usar um AtomicBoolean, criado no teu main, passado como parametro para a Thread e para o menu e alterado pelo menu quando a execução terminar.

1 curtida

Confesso que nunca tinha houvido falar sobre BlockingQueue e AtomicBoolean, mas estou no começo dos estudos, então…
Li a documentação dos dois, li outros artigos e consegui implementar.

Deu certo finalizar a thread e também a questão do sleep.

Muito show, valeu!

A quem interessar posteriormente que acessar esse tópico, assim ficou o código com as melhorias passadas pelo nosso amigo.

No try/catch do método run, sei que o ideal é aproximar o try o máximo possível da finalidade, ou seja, deixar somente o Documentos documento = doc.poll(1, TimeUnit.SECONDS); dentro dele, mas eu teria que inicializar o objeto fora dele e usá-lo dentro para depois passar como parâmetro dentro do if e do impressaoDocumento, enfim, achei melhor assim.

import java.util.InputMismatchException;
import java.util.Queue;
import java.util.Scanner;
import tadeu.fila.labs.Documentos;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.LinkedBlockingQueue;

public class Arquivo {

public static void main(String[] args) {

	Scanner scan = new Scanner(System.in);
	
	AtomicBoolean rodarThread = new AtomicBoolean(true);

	Queue<Documentos> filaDoc = new LinkedBlockingQueue<>();

	Impressora print = new Impressora(filaDoc, rodarThread);

	//RESOLVER PROBLEMA DE LOOP INFINITO SE DIGITAR LETRAS AO INVES DE NÚMEROS
	menu(scan, filaDoc, rodarThread);


}

public static void adicionarDocumento(Scanner scan, Queue filaDoc) {

	System.out.println("Digite o nome do documento:");
	String nomeDoc = scan.next();

	System.out.println("Digite a quantidade de páginas:");
	int qtdPaginas = scan.nextInt();

	Documentos doc = new Documentos(nomeDoc, qtdPaginas);

	synchronized(filaDoc) {
		filaDoc.add(doc);
	}
	System.out.println("Documento adicionado com sucesso!");
}

public static void menu(Scanner scan, Queue filaDoc, AtomicBoolean rodarThread) {

	boolean menuAtivo = true;
	int opcaoMenu = 0;
	while (menuAtivo) {
		System.out.println("1 - Adicionar documentos" + "\n" + "2 - Visualizar fila de impressão" + "\n" + "3 - Sair do Menu" );
		try {
			opcaoMenu = scan.nextInt();
		}
		catch(InputMismatchException e) {
			System.out.println("Digite apenas o número da opção desejada!");
		}
			menuAtivo = executarOpcao(opcaoMenu, filaDoc, scan, rodarThread);

	}
}

public static boolean executarOpcao(int opcaoMenu, Queue filaDoc, Scanner scan, AtomicBoolean rodarThread) {

	synchronized(filaDoc) {

		boolean menuAtivo;
		switch (opcaoMenu) {

		case 1:
			adicionarDocumento(scan, filaDoc);
			break;
		case 2:
			System.out.println(filaDoc.toString());
			break;
		case 3:
			boolean resposta = rodarThread.compareAndSet(true, false);
			if (resposta) {
				System.out.println("Programa Finalizado!");
			} else {
				System.out.println("Em execução");
			}
			return menuAtivo = false;
		default:
			break;
		}
		return menuAtivo = true;
	}
}

}

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Queue;

public class Impressora implements Runnable{

private LinkedBlockingQueue<Documentos> doc;
private AtomicBoolean rodarThread;

public Impressora(Queue<Documentos> doc, AtomicBoolean rodarThread) {
	this.doc = (LinkedBlockingQueue<Documentos>) doc;
	this.rodarThread = rodarThread;
	Thread t = new Thread(this);
	t.start();
}


public void run() {

	boolean retorno = rodarThread.get();
	while (retorno) {

		try {
			retorno = rodarThread.get();
			Documentos documento = doc.poll(1, TimeUnit.SECONDS);
			if (documento != null) {
				impressaoDocumento(documento);
			}
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public synchronized void impressaoDocumento(Documentos doc) {

	int tamanhoDoc = doc.getQtdPaginas();
	String nomeDoc = doc.getNome();

	System.out.println("Iniciando impressão do documento: " + nomeDoc);

	for (int i = 0; i < tamanhoDoc; i++) {
		System.out.println("Documento: " + nomeDoc);
		int paginaEmImpressao = i + 1;
		System.out.println("Imprimindo página: " + paginaEmImpressao + " de " + tamanhoDoc);
		try {
			Thread.sleep(500);
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	System.out.println(nomeDoc + " foi impresso com sucesso!");
}

}

public class Documentos {

private String nome;
private int qtdPaginas;
private boolean documentoImpresso;

public Documentos(String nome, int qtdPaginas) {
	this.nome = nome;
	this.qtdPaginas = qtdPaginas;
	this.documentoImpresso = false;	}

public String getNome() {
	return this.nome;
}

public int getQtdPaginas() {
	return this.qtdPaginas;
}

@Override
public String toString() {
	System.out.println();
	return "Documento: " + nome + ", Quant. Páginas: " + qtdPaginas ;
}

}