Java 多线程、可重用、可运行且具有特定于调用方的操作
给定两台服务器,Java 多线程、可重用、可运行且具有特定于调用方的操作,java,multithreading,Java,Multithreading,给定两台服务器,Server1.java和Server2.java。他们的任务是以相同的方式从客户机套接字收集一些数据,然后对这些数据执行不同的操作 首先,它们都将每个客户端套接字连接委托给一个新线程,以便能够同时处理多个客户端。当它们执行相同的操作来收集数据时,该线程的Runnable的run()方法中的代码对于两台服务器可能是相同的。。所以基本上他们都可以使用同一个类来创建线程 但是:问题是,在这个可运行程序中的某个地方,服务器作为另一个非阻塞操作已经做了不同的事情,因此基本上应该从这个线程
Server1.java
和Server2.java
。他们的任务是以相同的方式从客户机套接字收集一些数据,然后对这些数据执行不同的操作
首先,它们都将每个客户端套接字连接委托给一个新线程,以便能够同时处理多个客户端。当它们执行相同的操作来收集数据时,该线程的Runnable的run()方法中的代码对于两台服务器可能是相同的。。所以基本上他们都可以使用同一个类来创建线程
但是:问题是,在这个可运行程序中的某个地方,服务器作为另一个非阻塞操作已经做了不同的事情,因此基本上应该从这个线程启动一个新线程,该线程的可运行程序对于服务器来说已经不同了。这一行对于两台服务器都不相同
这就是为什么我现在无法重用Runnable的其他部分,尽管除了一行代码外,这两个服务器的Runnable完全相同
我说清楚了吗
(我可以想到的一个选项是,创建原始线程时,使用一个参数告诉它应该在该点调用哪个Runnable,但这不是一件好事。)
那么正确的方法是什么呢?这完全是我试图实现的正常程序吗
代码片段: 在
Server1.java
和Server2.java
中:
/* Creating a client socket every time a client connects to
* the server and delegating its management to a new thread... */
for (; ; ) { new Thread(new DataReceiver(serverSocket.accept())).start(); }
public class DataReceiver implements Runnable {
private Socket clientSocket;
private BufferedReader socketIn;
public DataReceiver(Socket clientSocket) { /* ... */ }
@Override
public void run() {
// ...
while ((inputLine = socketIn.readLine()) != null) {
// ...
new Thread(new ThisClassOrThatClass()).start(); //the only difference
// ...
}
// ...
}
}
在DataReceiver.java
中:
/* Creating a client socket every time a client connects to
* the server and delegating its management to a new thread... */
for (; ; ) { new Thread(new DataReceiver(serverSocket.accept())).start(); }
public class DataReceiver implements Runnable {
private Socket clientSocket;
private BufferedReader socketIn;
public DataReceiver(Socket clientSocket) { /* ... */ }
@Override
public void run() {
// ...
while ((inputLine = socketIn.readLine()) != null) {
// ...
new Thread(new ThisClassOrThatClass()).start(); //the only difference
// ...
}
// ...
}
}
我只看到评论/你的帖子中已经列出的选项,还有一些变化:
for (; ; ) { new Thread(new DataReceiver(serverSocket.accept(), () -> new ThisClass())).start(); }
然后:
public class DataReceiver implements Runnable {
private Socket clientSocket;
private BufferedReader socketIn;
private Supplier<Runnable> runnableSupplier;
public DataReceiver(Socket clientSocket, Supplier<Runnable> runnableSupplier) { /* ... */ }
@Override
public void run() {
// ...
while ((inputLine = socketIn.readLine()) != null) {
// ...
new Thread(runnableSupplier.get()).start();
// ...
}
// ...
}
}
公共类DataReceiver实现可运行{
私有套接字clientSocket;
私用缓冲阅读材料;
私人供应商经营的供应商;
公共数据接收器(套接字clientSocket,供应商runnableSupplier){/*…*/}
@凌驾
公开募捐{
// ...
而((inputLine=socketIn.readLine())!=null){
// ...
新线程(runnableSupplier.get()).start();
// ...
}
// ...
}
}
您可以使用方法getHandlerRunnable()
创建自定义接口处理程序
,而不是使用现有的通用供应商
或者,您可以通过不使用
getHandlerRunnable()
而简单地使用handleSomething(…)
的方式来稍微更改逻辑,并让该方法创建一个新线程并执行一些操作。我是否已经讲清楚了-不完全是,您描述代码太多,请展示它。我能想到的一个选择是,创建原始线程时使用一个参数,告诉它在该点应该调用哪个Runnable,但这不是一件好事我不同意,这听起来并不太糟糕。您不必传入可运行接口,您可以传入实现某个接口的任何对象实例,并在给定点调用该接口方法。Thread类接受可运行接口,因此您可以为server1和server2类实现可运行接口,并使用不同的逻辑从它们创建线程。问题出在哪里?创建一个名为“HandlerSupplier”的接口,您实现了两次,对于一台服务器,您总是返回一个new ThisClass()
,对于另一台服务器,您总是返回new ThatClass()
,假设两者都有一个Runnable
作为超级类型。您甚至可以删除自定义接口,只需使用Supplier
@tom,这是一个lambda表达式,以防您还不知道该术语,以前您必须创建一个实现该接口的匿名类,这样做只会大大缩短。我发现了它的作用。