简体   繁体   English

Java中线程的同步

[英]Synchronization in threads for Java

I have a home grown web server in my app. 我的应用程序中有一个自制的Web服务器。 This web server spawns a new thread for every request that comes into the socket to be accepted. 此Web服务器为进入要接受的套接字的每个请求生成一个新线程。 I want the web server to wait until a specific point is hit in the thread it just created. 我希望Web服务器等到它刚创建的线程中的特定点被命中。

I have been through many posts on this site and examples on the web, but cant get the web server to proceed after I tell the thread to wait. 我已经浏览过本网站上的很多帖子和网络上的例子,但在告诉线程等待之后,我无法继续使用Web服务器。 A basic code example would be great. 一个基本的代码示例会很棒。

Is the synchronized keyword the correct way to go about this? synchronized关键字是正确的方法吗? If so, how can this be achieved? 如果是这样,怎么能实现呢? Code examples are below of my app: 代码示例在我的应用程序下面:

Web Server 网络服务器

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);
  }
}

Thread code 线程代码

public void run() {
  //code here

  //notify web server to continue here
}

Update - Final code is as below. 更新 - 最终代码如下。 The HttpRequest does just call resumeListener.resume() whenever I send a response header (of course also adding the interface as a separate class and the addResumeListener(ResumeListener r1) method in HttpRequest ): 所述HttpRequest不只是调用resumeListener.resume()每当我发送响应报头(当然也加入该接口作为一个单独的类和addResumeListener(ResumeListener r1)在方法HttpRequest ):

Web Server portion 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);
  }
}

You can use java.util.concurrent.CountDownLatch with a count of 1 for this. 您可以使用java.util.concurrent.CountDownLatch ,计数为1。 Arrange for an instance of it to be created and shared by the parent and child thread (for example, create it in HttpRequest 's constructor, and have it retrievable by a member function). 安排由父线程和子线程创建和共享的实例(例如,在HttpRequest的构造函数中创建它,并使其可由成员函数检索)。 The server then calls await() on it, and the thread hits countDown() when it's ready to release its parent. 然后服务器在其上调用await() ,当线程准备释放其父节点时,线程会点击countDown()

You probably need to use a Java Condition . 您可能需要使用Java Condition From the docs: 来自文档:

Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. 条件(也称为条件队列或条件变量)为一个线程提供暂停执行(“等待”)的手段,直到另一个线程通知某个状态条件现在可能为真。

First of all, I echo the sentiment of others that re-inventing the wheel here will most likely lead to a variety of issues for you. 首先,我赞同其他人的观点,即在这里重新发明轮子很可能会为你带来各种各样的问题。 However, if you want to go down this road anyway what you are trying to do is not difficult. 但是,如果你想沿着这条路走下去,那么你要做的事情并不困难。 Have you experimented with Jetty? 您是否尝试过Jetty?

Maybe something like this: 也许是这样的:

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;
  }
}

Run under a debugger and set a breakpoint? 在调试器下运行并设置断点?

If unfeasible, then read a line from System.in? 如果不可行,那么从System.in读取一行?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM