Executar função/terefa em segundo plano

12 respostas
WRYEL

:? A duvida é a seguinte, como eu faço para disparar uma função em modo background ? explicando melhor …

eu chamar uma função que contenha o trecho:

try{
	for(int i=0;i<5;i++){ // faz de conta que sao 60 segundos ...
		Thread.sleep(1000);	
	}
} catch(Exception e){
}

sem que ela trave o programa impedindo de eu fica realizando ações (quero que ela seja executa por exemplo enquanto meu botão esteja LIGADO).

segue um programinha básico para entender melhor a ideia:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class guj extends JFrame implements WindowListener, ActionListener{
	private static final long serialVersionUID = 1L;
	
	JPanel painel = new JPanel();
	JButton botao = new JButton("INICIAR");

	public guj(){
		this.setLayout(null);
		this.setTitle("Eventos Duplos - guj");
		this.setResizable(false);
		this.setSize(400,300);
		this.addWindowListener(this);
		
		this.add(this.painel);
		this.painel.setBounds(3,3,389,269);
		this.painel.setBackground(new Color(210,210,210));
		
		this.botao.setBackground(new Color(175,10,10));
		this.painel.add(this.botao);
		this.botao.setBounds(300,200,50,30);
		this.botao.addActionListener(this);		
		
		this.setVisible(true);
	}	
	
	public static void main(String args[]){
		new guj();
	}

	@Override
	public void actionPerformed(ActionEvent o) {
		Object object = o.getSource(); // SEM CAST
		if(o.getSource().equals(botao)){
			if(((JButton) object).getBackground().toString().equals("java.awt.Color[r=175,g=10,b=10]")){
				((JButton) object).setBackground(new Color(0,185,0));
				((JButton) object).setText("PARAR");
			} else {
				((JButton) object).setBackground(new Color(175,10,10));
				((JButton) object).setText("INICIAR");
			}
		}
		
		iniciarContagem();
		
	}
	
	public void iniciarContagem(){
		try{
			for(int i=0;i<5;i++){ // faz de conta que sao 60 segundos ...
				Thread.sleep(1000);	
			}
			JOptionPane.showMessageDialog(null, "60 segundos");
		} catch(Exception e){
		}		
	}
	
	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}

To aceitando qualquer tipo de ideia, sugestão, ou aonde procurar, ou até mesmo dicas sobre aonde ler :slight_smile:
obrigado!

12 Respostas

71C4700

Bem vc poderia criar uma Thread só pra fazer o que voce deseja neste intervalo de tempo e controla isso onde voce faz chamada a este processamento paralelo.
Mais ou menos assim

public class FazAlgo extends Thread implements Runnable{
private int tempo;
public FazAlgo(int tempo){
super();
this.tempo = tempo;
}
public void run(){
this.sleep(tempo);  //Executa algo
}

}
//Setters e Getters

E na Classe principal chama

Thread thread = new Thread(new FazAlgo(1100));// onde este numero é o intervalo de tempo ai voce controla este tempo aki
thread.start();

Posta a resposta !!!

WRYEL

O cara valeu pela ajuda, mas acho que você não entendeu direito o que eu quis dizer, ou eu que não soube entender sua explicação, to postando ocodigo com a adição da classe que você me passou:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class guj extends JFrame implements WindowListener, ActionListener{
	private static final long serialVersionUID = 1L;
	
	JPanel painel = new JPanel();
	JButton botao = new JButton("INICIAR");
	Thread thread = null;

	public guj(){
		this.setLayout(null);
		this.setTitle("Eventos Duplos - guj");
		this.setResizable(false);
		this.setSize(400,300);
		this.addWindowListener(this);
		
		this.add(this.painel);
		this.painel.setBounds(3,3,389,269);
		this.painel.setBackground(new Color(210,210,210));
		
		this.botao.setBackground(new Color(175,10,10));
		this.painel.add(this.botao);
		this.botao.setBounds(300,200,50,30);
		this.botao.addActionListener(this);		
		
		this.setVisible(true);
	}	
	
	public static void main(String args[]){
		new guj();
	}

	@Override
	public void actionPerformed(ActionEvent o) {
		Object object = o.getSource(); // SEM CAST
		if(o.getSource().equals(botao)){
			if(((JButton) object).getBackground().toString().equals("java.awt.Color[r=175,g=10,b=10]")){
				((JButton) object).setBackground(new Color(0,185,0));
				((JButton) object).setText("PARAR");
				this.thread = new Thread(new FazAlgo(6000));
				this.thread.run();
			} else {
				((JButton) object).setBackground(new Color(175,10,10));
				((JButton) object).setText("INICIAR");
			}
		}
		
		iniciarContagem();
		
	}
	
	public void iniciarContagem(){
				
	}
	
	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	public class FazAlgo extends Thread implements Runnable{
		private int tempo;

		public FazAlgo(int tempo){
			super();
			this.tempo = tempo;
		}
		
		@SuppressWarnings("static-access")
		public void run(){
			try{
				this.sleep(tempo);
				JOptionPane.showMessageDialog(null, "Fim");
			} catch(Exception e){
		
			}
		}
		
	}
	
}

A ideia mais específica é a seguinte, vamos supor que eu aperte no botão LIGAR e nele fica rodando no fundo 1 timer de 60 segundos.
durante esses 60 segundos, eu posso optar por desligar esse botão LIGAR, quando chegar no 60, ele checa se o botão está ligado, se estiver, ele manda 1 um alerta na tela.

lembrando que eu quero durante esses 60 segundos, ficar alterando o botão, LIGAR e DESLIGAR ou fazer qualquer outra coisa dentro do meu programa.

com esse exemplo ai em cima, o programa fica travado esperando que o thread.run() termine, o que não faz sentido esperar nesse caso =P

zehnogueira

tente criar uma nova classe separada, e chame ela a partir da classe principal…
nao tem como vc fazer um laço em forma de metodo…
criando um nova classe voce pode disparar-la em forma de thread…

tentei resumir ai… mas se nao ficar muito claro poste aqui q tente ser mais especifico…

aqui explica certinho:

http://209.85.215.104/search?q=cache:HVO43vMmk_wJ:www.ime.usp.br/~gold/cursos/2004/mac438/aulaJava.pdf+exemplo+thread+java&hl=pt-BR&ct=clnk&cd=2&gl=br&ie=UTF-8

abrxxxx

P

Olá, voce pode fazer isso chamando um metodo como o colega acima citou mas, a forma mais profissional e coerente e a criação de Threads.

Uma thread e um processo que fica na fila de espera para executar no processador. Mas o processador so contem um canal de dados, logo ele so pode executar uma tarefa por vez. Portanto o escalonador de processos seleciona as threads a serem executadas.

Mas uma coisa, so uma coisa pode ocorrer num computador convencional por vez. Entao ou voce deixa o form falando (oi) ou entao deixa ele contando algo. Pracontrolar isso em Java é MUITO simples, ele faz tudo isso por voce, em uma linguagem tipo C++ vc ia ver o que é o cão.

E ah, como as threads ocorrem de forma concorrente vc nunca tem como predefinir quem ocorrera primeiro, o escalonador de processos que definirá.

Entao o certo pra fazer isso no caso, é criar uma classe threaded, que implementa Runnable e sobrescreve o metodo Run(). Nao é bom extender a classe thread, pois assim voce vai perder em uma serie de coisas. E voce pode implementar quantas interfaces quiser em uma classe.

Portanto, eu recomendaria:

public class Timer implements Runnable {

public void run() {
iniciarTimer();
}
}

Depois voce pode mandar iniciar tal thread em outra classe pelo metodo start().

Se quiser mais dicas sobre thread, no java.sun.com tem MUITA coisa.

Abração

71C4700

Gostei da soluçao do Sergio Figueras, só acrecentaria que a forma(estado) como a thread se comporta poderia ser controlada na classe que a chama. Mas ou menos assim. A thread seria iniciada e a cada intervalo de tempo determinado ela executaria a tarefa solicitada e controlada na classe principal.
Sim, Obrigado Sergio Figueras, pela dica de não extender a classe Thread, é por que tava um pouco apressado -muito trabalho- mas agradeço muita pela dica.

ViniGodoy

No Java há várias maneiras.

Você pode criar outra thread, como disse o Sergio, seja através da classe Thread ou através da classe ExecutorService. Por isso é importante implementar Runnable ao invés de estender thread.

Você também pode agendar tarefas para serem executadas de tempos em tempos através da classe Timer. Na verdade, existem 2 classes como essa. Se sua tarefa for só uma atualização de tela, há classe javax.swing.Timer que dispara eventos diretamente na thread do swing. Caso contário, existe a classe java.util.Timer, que dispara eventos numa thread separada.

Aqui nesse post tem 3 exemplos funcionais de um reloginho, usando a classe thread e as classes de timer. Ele fica sendo atualizado em segundo plano, como vc gostaria de fazer (não esqueça de ver a página 2):

http://www.guj.com.br/posts/list/52964.java#279083

ViniGodoy

Ainda bem que na próxima versão, o C++0x já vai incluir uma série de funcionalidades para threads:


Vale lembrar que a biblioteca boost também tem muitas classes úteis, que tornam trabalhar com Threads no C++ uma tarefa muito mais fácil.

Agora… cuidado com a afirmação de que multithreading é simples em Java. Para tarefas simples, como implementações de timers, é realmente. Mas para coisas mais complexas, onde começa a existir sincronização de diferentes threads e acesso concorrente, nenhuma implementação multi-threading é simples. Ela é, no máximo, “mais simples”. :wink:

WRYEL

Bom dia pessoal, agradeço o interesses de vocês aqui, li cada resposta e tentei no meu tempo vago jogar codigo pra la, e codigo pra ca, sinto que tou chegando perto mais eu ainda não consegui fazer o que eu quero, se possível informem apenas aonde é que eu to errando :confused:

ele ainda continua travando a tela como eu disse acima, mas eu ja entendi o conceito básico de threads, pelo menos eu acho, segue o codigo que eu to parado aqui:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class guj extends JFrame implements WindowListener, ActionListener{
	private static final long serialVersionUID = 1L;
	
	JPanel painel = new JPanel();
	JButton botao = new JButton("INICIAR");
	JButton btntempo = new JButton("100");
	autoclick thread = new autoclick();

	public guj(){
		this.setLayout(null);
		this.setTitle("Eventos Duplos - guj");
		this.setResizable(false);
		this.setSize(400,300);
		this.addWindowListener(this);
		
		this.add(this.painel);
		this.painel.setBounds(3,3,389,269);
		this.painel.setBackground(new Color(210,210,210));
		
		this.botao.setBackground(new Color(175,10,10));
		this.painel.add(this.botao);
		this.botao.setBounds(300,200,50,30);
		this.botao.addActionListener(this);
		
		this.painel.add(this.btntempo);
		this.btntempo.setBounds(10,10,50,30);
		this.btntempo.addActionListener(this);
		
		this.setVisible(true);
		thread.tempo = (long) 100;
		thread.run();
	}	
	
	public static void main(String args[]){
		new guj();
	}

	@Override
	public void actionPerformed(ActionEvent o) {
		Object object = o.getSource(); // SEM CAST
		if(o.getSource().equals(botao)){
			if(((JButton) object).getBackground().toString().equals("java.awt.Color[r=175,g=10,b=10]")){
				((JButton) object).setBackground(new Color(0,185,0));
				((JButton) object).setText("PARAR");
				this.thread.ligado=1;
			} else {
				((JButton) object).setBackground(new Color(175,10,10));
				((JButton) object).setText("INICIAR");
				this.thread.ligado=0;
			}
		}
		
		if(o.getSource().equals(btntempo)){
			setarTempo();
		}
	}
	
	public void setarTempo(){
		String temp = (String) JOptionPane.showInputDialog(null, "Digite uma quantidade de segundos");
		this.btntempo.setText(temp);
		thread.tempo = (long) Long.parseLong(temp);	
	}
	
	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}

Classe separada, autoclick (titulo auto-explicativo) :stuck_out_tongue:

import java.awt.Robot;
import java.awt.event.InputEvent;

public class autoclick implements Runnable {
	
	byte ligado = (byte) 0;
	long tempo = 100;
	
	@Override
	public void run() {
		try{
			Robot robot = new Robot();
			while(this.ligado==1){
			Thread.sleep(this.tempo);
			robot.mousePress(InputEvent.BUTTON1_MASK);
	        robot.mouseRelease(InputEvent.BUTTON1_MASK);
			}
		} catch(Exception e){
			
		}
		this.run();
	}	
}

@vinigodoy: eu li seu tópico, o ultimo exemplo com Timer está bem claro, assim que eu resolver com thread vou testar aquele também.

@zehnogueira: eu tambem fiz dentro da classe principal, e aparentemente esá dando o mesmo erro como você.

@71C4700: para controlar a thread eu adicionei uma variavel na classe que implemento Runnable comovocê ve no exemplo.

Acho que eu to cometendo algum erro besta ou to usando as thread de forma errada =|

será que é porque eu não do criando variaveis dentro da classe implementada por Runnable ?

ViniGodoy
  1. Renomeie a classe autoclick para AutoClick;
  2. Declare a variável assim:
AutoClick autoClick = new AutoClick();

Ela não é uma thread ainda.
3. Para iniciar a thread, usa-se a classe Thread. O método que cria uma nova thread é o start() não o método run(). Então, inicie sua thread assim:

//Crie uma variável da classe thread
Thread threadControl = new Thread(autoClick);
// um nome a thread que será criada. Isso é util no debbuger
threadControl.setName("Auto click thread");
//Defina a thread como deamon. Threads que não são Daemon mantém a aplicação Java viva.
//Se  houverem threads deamon ativas, a aplicação java fecha.
threadControl.setDaemon(true);
//Inicie a nova thread usando o método start(). A thread iniciará no run().
//Chamar o método run() diretamente faz com que ele seja executado na thread atual
//Não numa nova thread.
threadControl.start();
  1. Dê uma olhada com carinho nas implementações usando Timer no link que eu te passei.
WRYEL

@ViniGodoy: Enquanto eu não tinha visto sua resposta eu fui ler pela 94023 vez o tutorial que o zehnogueira deixou, ai eu percebi que minha thread não estava sendo passada nenhum argumento, dai mexidali, mexi daqui, depois dumas 2 horas quebrando a cara, funcionou e saiu:

import java.awt.Color;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class guj extends JFrame implements WindowListener, ActionListener{
	private static final long serialVersionUID = 1L;
	
	JPanel painel = new JPanel();
	JButton botao = new JButton("INICIAR");
	JButton btntempo = new JButton("1000");
	Thread thread = null;
	static byte ligado = 0;
	static long tempo = 1000;

	public guj(){
		this.setLayout(null);
		this.setTitle("Eventos Duplos - guj");
		this.setResizable(false);
		this.setSize(400,300);
		this.addWindowListener(this);
		
		this.add(this.painel);
		this.painel.setBounds(3,3,389,269);
		this.painel.setBackground(new Color(210,210,210));
		
		this.botao.setBackground(new Color(175,10,10));
		this.painel.add(this.botao);
		this.botao.setBounds(300,200,50,30);
		this.botao.addActionListener(this);
		
		this.painel.add(this.btntempo);
		this.btntempo.setBounds(10,10,50,30);
		this.btntempo.addActionListener(this);
		
		this.setVisible(true);
		
	}	
	
	public static void main(String args[]){
		new guj();
	}

	@Override
	public void actionPerformed(ActionEvent o) {
		Object object = o.getSource(); // SEM CAST
		if(o.getSource().equals(botao)){
			if(((JButton) object).getBackground().toString().equals("java.awt.Color[r=175,g=10,b=10]")){
				((JButton) object).setBackground(new Color(0,185,0));
				((JButton) object).setText("PARAR");
				ligado=1;
				thread = new Thread(new autoclick());
				thread.start();
			} else {
				((JButton) object).setBackground(new Color(175,10,10));
				((JButton) object).setText("INICIAR");
				ligado=0;
			}
		}
		
		if(o.getSource().equals(btntempo)){
			setarTempo();
		}
	}
	
	public void setarTempo(){
		String temp = (String) JOptionPane.showInputDialog(null, "Digite uma quantidade de segundos");
		this.btntempo.setText(temp);
		tempo = (long) Long.parseLong(temp);	
	}
	
	public class autoclick implements Runnable {
		
		@Override
		public void run() {
			try{
				Robot robot = new Robot();
				Thread.sleep(tempo);
				while(ligado==1){			
				robot.mousePress(InputEvent.BUTTON1_MASK);
		        robot.mouseRelease(InputEvent.BUTTON1_MASK);	       
				}
			} catch(Exception e){
				
			}
		}	
	}
	
	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}

@ViniGodoy: pode ter certeza que cada dica que você segeriu aqui será relida e usada por mim, num to podendo testa tudo porque estou no trampo agora, mas chegando em casa eu vo dar uma olhada denovo e arrumar melhor o código, posto um .zip aqui melhorado pra quem quiser RE-aproveitar =)

obrigado a todos !

mpa700

acho que vc quis dizer executar uma aplicação em segundo plano no início. eu gostaria de saber se eu posso usar esse código pra executar a tarefa independente do que tô fazendo, por exemplo eu abro um filme depois de executar a ação, ai ela faz tudo que eu pedir, entra no site, loga, compra, tira foto, fecha o site (ou nem precisa exibir isso acontecer), depois quando o filme acabar e eu fechar o player a aplicação iria exibir compra concluída com sucesso e os dados da transação e um botão de ok, ou se der erro uma opção pra fechar ou tentar de novo.

aszarael

Cara, se você quiser executar por agendamento, pode fazer da seguinte maneira

GregorianCalendar gc = new GregorianCalendar();  
		gc.setTime(new Date());  
		  
		gc.add(Calendar.MINUTE,0);
		
        Date time = gc.getTime();
		
		 final Timer t = new Timer();
		 
	        t.schedule(new TimerTask() {
	            @Override
	            public void run() {
	            	
	            	
	            	Process p = null;
	            	
	        		try {
	        			
	        			p = Runtime.getRuntime().exec(Arquivobat ao ser executado ou o que desejar);
	        			
	        		} catch (IOException e) {
	        			e.printStackTrace();
	        		}  
	        		
	        		BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); 
	        		
	        		try {
	        			String vLinha;  
	        			while ((vLinha = input.readLine()) != null) {  
	        			  System.out.println(vLinha);  
	        			  
	        			}
	        		} catch (IOException e) {
	        			e.printStackTrace();
	        		}  

	                t.cancel();
	            }
	 
	        }, time);
Criado 18 de julho de 2008
Ultima resposta 12 de ago. de 2015
Respostas 12
Participantes 7