Sincronización en hilos para Java
-
05-07-2019 - |
Pregunta
Tengo un servidor web propio en mi aplicación. Este servidor web genera un nuevo hilo para cada solicitud que entra en el socket para ser aceptada. Quiero que el servidor web espere hasta que se toque un punto específico en el hilo que acaba de crear.
He visto muchas publicaciones en este sitio y ejemplos en la web, pero no puedo hacer que el servidor web continúe después de haberle dicho al hilo que espere. Un ejemplo de código básico sería genial.
¿Es la palabra clave sincronizada la forma correcta de hacerlo? Si es así, ¿cómo se puede lograr esto? Los ejemplos de código están debajo de mi aplicación:
Servidor web
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.run();
///////////////////////////////
wait here until notifed to proceed
///////////////////////////////
} catch (Exception e) {
e.printStackTrace(logFile);
}
}
Código de hilo
public void run() {
//code here
//notify web server to continue here
}
Actualización: el código final es el siguiente. El HttpRequest
solo llama a resumeListener.resume ()
cada vez que envío un encabezado de respuesta (por supuesto, también agrego la interfaz como una clase separada y el addResumeListener (ResumeListener r1 )
método en HttpRequest
):
Parte del servidor web
// server infinite loop
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
request.addResumeListener(new ResumeListener() {
public void resume() {
//get control of the lock and release the server
synchronized(locker) {
locker.notify();
}
}
});
synchronized(locker) {
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.start();
//tell this thread to wait until HttpRequest releases
//the server
locker.wait();
}
} catch (Exception e) {
e.printStackTrace(Session.logFile);
}
}
Solución
En primer lugar, me hago eco del sentimiento de los demás de que reinventar la rueda aquí probablemente te llevará a una variedad de problemas para ti. Sin embargo, si quieres seguir este camino de todos modos, lo que estás tratando de hacer no es difícil. ¿Has experimentado con Jetty?
Tal vez algo como esto:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
Otros consejos
Puede usar java.util.concurrent .CountDownLatch con un conteo de 1 para esto. Organice una instancia de la misma para crearla y compartirla con el subproceso principal y secundario (por ejemplo, créela en el constructor de HttpRequest
y pídale que la función miembro la pueda recuperar). El servidor luego llama a await ()
en él, y el hilo golpea a countDown ()
cuando está listo para liberar a su padre.
Probablemente necesite usar un Java Condición . De los documentos:
Condiciones (también conocidas como condición colas o variables de condición) proporcionan un medio para un hilo para suspender ejecución (esperar " esperar ") hasta que se le notifique por otro hilo que algún estado La condición ahora puede ser verdadera.
¿Se ejecuta bajo un depurador y establece un punto de interrupción?
Si no es factible, entonces lee una línea de System.in?