Foro sobre Java SE > Concurrencia y Sockets
invokeLater no coloca el bloque de código en una tarea paralela al EDT, sino que coloca ese bloque al final de la cola del EDT.
No se puede usar invokeLater para crear concurrencia con el EDT.
Del código fuente de la clase EventQueue (JavaSE 1.8)
/**
* Causes runnable
to have its run
* method called in the {@link #isDispatchThread dispatch thread} of
* {@link Toolkit#getSystemEventQueue the system EventQueue}.
* This will happen after all pending events are processed.
*
* @param runnable the Runnable
whose run
* method should be executed
* asynchronously in the
* {@link #isDispatchThread event dispatch thread}
* of {@link Toolkit#getSystemEventQueue the system EventQueue}
* @see #invokeAndWait
* @see Toolkit#getSystemEventQueue
* @see #isDispatchThread
* @since 1.2
*/
public static void invokeLater(Runnable runnable) {
Toolkit.getEventQueue().postEvent(
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
}
Si se necesita ejecutar código en una tarea paralela al EDT, puede hacerse de dos maneras:
1.- El bloque de código no usa métodos de Swing que usen el RepaintManager
Puede usarse la clase Executor para crear un pool de tareas paralelas, y realizar un submit con un Runnable.
http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
2.- En caso contrario, debe usarse SwingWorker.
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
SwingWorker no lo puedo usar choces, ya que uso java 7. Podrias ser tan amable de indicarme donde tengo que colocar el codigo para que use un thread paralelo y no se me bloquee el thread principal?
Gracias.
SwingWorker se puede usar en Java 7 y 8 sin problemas. Existe en el JDK desde Java 6
http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html
Buenas tardes. El problema que tengo es con la concurrencia y sockets. Estoy empezando con sockets y estoy haciendo un chat para aprender mientras leo/practico. Bien, el problema es que el servidor al esperar la conexión de los clientes (clienteConectado = servidor.accept()) me freezea la UI y tengo que matar el proceso.
He probado colocando el inicio del servidor en un hilo con SwingUtilies, pero no me sirve nada. Les dejo el codigo.
Clase Servidor:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Servidor {
private ServerSocket servidor = null;
private DataOutputStream salida = null;
private DataInputStream entrada = null;
private Socket clienteConectado = null;
private static final int PUERTO = 9999;
public Servidor() {
}
public void iniciar() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
try {
conectarServidor();
recibirMensaje();
} catch (IOException | NullPointerException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
} finally { cerrarFlujos(); }
}});
}
public void recibirMensaje() throws IOException, NullPointerException {
entrada = new DataInputStream(clienteConectado.getInputStream());
String mensajeRecibido = entrada.readUTF();
System.out.println("El cliente ha dicho:\t"+mensajeRecibido);
}
public void conectarServidor() throws IOException {
servidor = new ServerSocket(PUERTO);
System.out.println("SERVER INICIADO");
clienteConectado = servidor.accept(); // espera que se conecte un cliente
}
public void cerrarFlujos() {
try {
if(salida != null) salida.close();
if(entrada != null) entrada.close();
if(clienteConectado != null) clienteConectado.close();
if(servidor != null) entrada.close();
} catch(IOException ioe) { System.out.println(ioe.getMessage()); }
}
}
Clase que controla ServidorUI (y de donde inicio el servidor):
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import pe.edu.unp.conexion.Servidor;
import pe.edu.unp.ui.ServidorUI;
public class ServidorUIControl implements ActionListener {
ServidorUI ui;
public ServidorUIControl (ServidorUI ui) {
this.ui = ui;
}
public void limpiarChat() {
ui.areachat.setText("");
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == ui.btnConectar) {
new Servidor().iniciar();
}
if(e.getSource() == ui.btnDesconectar) {
}
if(e.getSource() == ui.btnLimpiar) {
this.limpiarChat();
}
if(e.getSource() == ui.btnSalir) {
ui.dispose();
}
if(e.getSource() == ui.txtMensaje) {
}
if(e.getSource() == ui.btnEnviar) {
}
}
}
Gracias por leer.