Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程、可重用、可运行且具有特定于调用方的操作_Java_Multithreading - Fatal编程技术网

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表达式,以防您还不知道该术语,以前您必须创建一个实现该接口的匿名类,这样做只会大大缩短。我发现了它的作用。