【问题标题】:Java Running Sequentially but concurrentlyJava 顺序但同时运行
【发布时间】:2014-06-05 10:38:21
【问题描述】:

这可能看起来很愚蠢,但它是否可以按顺序运行但也可以同时使用线程?例如看下面的代码:

public void processMessage(Socket socket) {
     char[] data = buildData(socket.getInputStream());
     int primaryKey = saveRecord(data);
     // do something else
}

public char[] buildData(InputStream inputStream) {
    return new char[5];
}

public int saveRecord(char[] data) {
   // save to database and return primary key
}

Runnable runnable = new Runnable() {
   public void run() {
        processMessage(socket.getInputStream());
   }
};
new Thread(runnable).start();

Runnable runnable2 = new Runnable() {
   public void run() {
       processMessage(socket.getInputStream());
   }
};
new Thread(runnable2).start();

我要做的是启动一个线程并执行全套方法,然后另一个线程启动并完全完成。这是因为我收到了一些数据,读取了数据,插入到数据库中,还有其他事情,但想避免数据库更新并发问题。

其实这是一个TCP应用,数据来自socket,数据不会立即到达。在我有一个单线程应用程序之前,但由于应用程序运行速度太慢并且来自套接字的数据没有到达之前,我引入了线程。现在全套数据都在TCP Socket上,但我想避免数据库并发问题。

以上仅为示例代码。

我了解线程的基础知识,并且我知道每个线程都有自己的堆栈,但我想正确地保持数据库插入/更新以避免任何数据冲突。

编辑:

private ServerSocket serverSocket;
private Socket socket;

public void acceptData() {
      serverSocket = new ServerSocket("somePort");
      socket = serverSocket.accept();
      Runnable runnable = new Runnable() {
          public void run() {
              processMessage(socket.getInputStream());
          }
      };
      new Thread(runnable).start(); 
}

这就是我正在做的。在每个循环中,我都会创建一个新线程,这样套接字就不会被阻塞,并且会在线程被并发管理的同时继续发送数据。

【问题讨论】:

  • 您能更清楚地了解您的要求吗?您是否希望在第二个线程运行之前等待第一个线程保证已完成其工作?如果是这样,那和顺序代码有什么区别?
  • 是的,我要第一个线程先完成。问题在于,在套接字层上,数据之前没有到达。当我开始介绍 Threads 时,TCP 套接字层上的全套数据正在被接收。
  • '顺序但同时'是一个矛盾的术语。

标签: java multithreading sockets tcp


【解决方案1】:

它看起来是一个经典的生产者/消费者模式,对吧?

用一个信号量同步两个线程看起来是可行的。

private Object semaphore = new Object();

public void processMessage(Socket socket) {
    synchronize(semaphore) {
        char[] data = buildData(socket.getInputStream());
        int primaryKey = saveRecord(data);
        // do something else
    }
}

public char[] buildData(InputStream inputStream) {
    return new char[5];
}

public int saveRecord(char[] data) {
    // save to database and return primary key
}

Runnable runnable = new Runnable() {
    public void run() {
        processMessage(socket.getInputStream());
    }
};
new Thread(runnable).start();

Runnable runnable2 = new Runnable() {
    public void run() {
        processMessage(socket.getInputStream());
    }
};
new Thread(runnable2).start();

有了这个实现,第一个接收消息的线程将启动 processMessage 执行,我们将停止另一个线程的执行,直到它完成。

这是你要找的吗?

【讨论】:

  • 我不明白。你能展示一些示例代码来解释一下吗?
  • 我了解线程的基础知识,我知道每个线程都有自己的堆栈,但我想保持数据库插入/更新正确,以避免任何数据冲突。
  • 你的意思是第一个收到消息的线程会启动 processMessage 执行,一旦完成,所有的步骤可能会转移到另一个线程启动?
  • 是的,真正发生的是第一个收到消息的线程将“关上门”来执行“同步”块内的代码。当它完成执行时......它将再次“开门”,下一次等待将执行代码。任何试图执行同步块的代码都会等到“门打开”。
  • 看起来这个解决方案不起作用。我需要对 processMessage() 调用的每个方法进行同步吗?看起来正在运行不同的线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 2011-09-09
  • 1970-01-01
  • 2013-08-13
相关资源
最近更新 更多