Duplicação de execução (JButton)

Boa noite, estou montando uma interface. Nela há um botão start que inicia uma Thread e transforma-se em botão stop (não na thread). Até aí, tudo bem, mas se eu aperto o botão consecutivamente (criando um start/stop/start/stop) ele acaba criando uma nova thread antes de parar a anterior, assim, fico com uma thread rodando extra e uma manuseável de acordo com o start/stop (é possível aumentar o número de threads prolongado o número de vezes que pressiona-se o botão).

Já tentei criar um método synchronizad, usar booleans e tudo mais que eu consegui imaginar pra tentar corrigir isso (impedir a criação de mais de 1 thread), mas nada dá certo…

Meu código:

package snow;

import java.io.IOException;

import javax.swing.JOptionPane;

/**
 * @author KaL
 */
public class Listeners
{
	private Sniffer sn;
	private GUI gui;
	private ProcessList pl;
	private PIDsHandler ph;
	private int pid = -1;
	private String recv, send;
	private boolean isRefreshing = false;
	
	public Listeners( GUI gui)
	{
		this.gui = gui;
		pl = new ProcessList();
		ph = new PIDsHandler(this.gui);;
	}

	private boolean load()
	{
		try{			
			int avaliablePID = pl.listProcessIDs()[0];
			if(!ph.isPID(avaliablePID))
				return false;

			String process = pl.getPIDProcess(avaliablePID);
			if(ProcessList.interrupted && !isRefreshing)
			{

				ProcessList.isProcessing = false;
				return false;
			}

			if(process == null && !isRefreshing)
				if(!ph.isProcess(process))
					return false;

			recv = pl.getPIDRecv(process);
			send = pl.getPIDSend(process);
			
			ph.addUsedPID(avaliablePID);
			setPID(avaliablePID);
			ProcessList.isProcessing = false;
			return true;
		} catch (IOException e) {
			gui.showOptionPane("Could not search for avaliable processes.", "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
			return false;
		}
	}
	
	public void start() 
	{
		new Thread()
		{
			public void run()
			{				
				if(getPID() < 0)
				{
					if(!load())
					{
						if(!ProcessList.interrupted)
							gui.startInvert();
					}
				}
				
				if(ProcessList.interrupted)
				{
					ProcessList.interrupted = false;
					return;
				}
				
				getGUI().refresh.setEnabled(true);
				
				sn = new Sniffer(recv, send, gui);
				setSniffer(sn);

				getSniffer().isRunning = true;
				getSniffer().run();
			}
		}.start();
    }
	
	public void stop(boolean disable)
	{
		if(isRefreshing && disable)
			gui.start.setEnabled(false);
			
		if(ProcessList.isProcessing)
			pl.interrupt();
		
		if(getSniffer() != null && getSniffer().isRunning)
			getSniffer().stopSniff();
				
	}
	
	public void setSniffer(Sniffer sn)
	{
		this.sn = sn;
	}
	
	public Sniffer getSniffer()
	{
		return sn;
	}
		
	public void setPID(int PID)
	{
		pid = PID;
	}
	
	public int getPID()
	{
		return pid;
	}
	
	public GUI getGUI()
	{
		return gui;
	}
}

Faça sua thread reabilitar o botão ao final do método run().

O botão não é desabilitado ao pressionado (aquele controlador é referente a um refresh que eu criei, este está funcionando)

Mas como vc dispara a thread? Eu geralmente proibia isso da maneira mais simples possível:

  1. Ao disparar a thread, desabilite o botão que permite o disparo;
  2. Reabilite no final do run.

Caso você não possa desabilitar o botão:

  1. Guarde o objeto da thread numa variável de instância;
  2. Ao tentar disparar essa thread novamente, teste se a variável não é nula. Somente se for, crie uma thread com new e dispare-a.

Como o run executa um loop infinito, fica inviável desabilitar o botão (pois o mesmo serve para interromper).

Coloquei a thread como você disse, mas aí quando eu dou start/stop (até aí, certo) e start de novo, ele dispara uma exceção:

[code]
Thread t;
public void start()
{
if(getThread() == null)
{
t = new Thread()
{
public void run()
{
if(getPID() < 0)
{
if(!load())
{
if(!ProcessList.interrupted)
gui.startInvert();
}
}

				if(ProcessList.interrupted)
				{
					ProcessList.interrupted = false;
					return;
				}
				
				getGUI().refresh.setEnabled(true);
				
				sn = new Sniffer(recv, send, gui);
				setSniffer(sn);

				getSniffer().isRunning = true;
				getSniffer().run();
			}
		};
		setThread(t);
	}
	getThread().start();
}

public void setThread(Thread t)
{
	this.t = t;
}

public Thread getThread()
{
	return t;	
}[/code]

[quote]Exception in thread “AWT-EventQueue-0” java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:595)
at snow.Listeners.start(Listeners.java:93)
at snow.GUI$13.actionPerformed(GUI.java:458)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
at java.awt.Component.processMouseEvent(Component.java:6267)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6032)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)[/quote]