Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/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_Android_Multithreading_Sockets - Fatal编程技术网

Java 从同一套接字读取的多线程

Java 从同一套接字读取的多线程,java,android,multithreading,sockets,Java,Android,Multithreading,Sockets,我正在开发一个显示服务器数据的应用程序。服务器不是我的,也不是很稳定。连接过多会使服务器崩溃 我的主活动中有一个到服务器的套接字,但有时我想打开读取数据并显示数据的子活动。我的问题是,我无法用同一个套接字实现这一点,必须为每个活动打开一个新的套接字。 每个活动都有一个线程,该线程从套接字读取数据,并根据需要更新该活动上的UI元素 为了在多个活动中使用同一套接字,我尝试在启动新活动之前关闭活动的inputReader,但这只会使应用程序挂起。如果我让它保持打开状态,那么新活动中的新线程永远不会收到

我正在开发一个显示服务器数据的应用程序。服务器不是我的,也不是很稳定。连接过多会使服务器崩溃

我的主活动中有一个到服务器的套接字,但有时我想打开读取数据并显示数据的子活动。我的问题是,我无法用同一个套接字实现这一点,必须为每个活动打开一个新的套接字。 每个活动都有一个线程,该线程从套接字读取数据,并根据需要更新该活动上的UI元素

为了在多个活动中使用同一套接字,我尝试在启动新活动之前关闭活动的inputReader,但这只会使应用程序挂起。如果我让它保持打开状态,那么新活动中的新线程永远不会收到任何数据。在启动新活动之前终止线程是不可能的,因为线程通常被read()函数阻塞

我是否可以有一个集中式线程来读取数据,然后将数据发送到其他活动中的所有其他线程,这样我就不必在每个活动中打开新的套接字


我觉得这是我问的一个非常基本的问题,但我无法找到解决办法

基本上你自己回答了你的问题:

我可以有一个集中式线程来读取数据,然后将数据发送到其他活动中的所有其他线程

当然,这样的事情是可能的。但是你必须坐下来,设计并实现它。您可以从定义一个合理的接口开始,该接口允许您的其他线程与该中心服务进行通信,例如:

enum RequestType { DO_THIS, DO_THAT };

interface ServerConnectionService<T> {
   List<T> performRequest(RequestType request);
}
enum RequestType{DO_THIS,DO_THAT};
接口服务器连接服务{
列出performRequest(请求类型请求);
}
意思是:不要让你的不同线程在这个套接字上进行“低级”对话,而是创建一个抽象,允许你说:“当我需要这种信息时,我就使用我的服务;它会向我返回一些特定的答案。”当然,这是一个非常通用的答案,但是你的问题也不是很具体

然后,下一步将是该接口的一些中心(可能是单例)实现;它在自己的线程上运行,并且可以由其他线程以同步的、定义良好的方式使用


最后一句警告:如果你没有拥有那台服务器,而且它的质量很低,给你带来了麻烦-这不是一个好的设置。因为无论你在代码中做了什么,如果服务器做得不好,用户都会认为你的应用程序是个问题。用户不在乎是否有操作n失败是因为某些远程服务器崩溃。因此,您的问题的另一个方面是:现在,您处于一个糟糕的境地。您应该花一些时间来寻找解决方法。否则,您将浪费大量时间为您正在处理的服务器构建变通方法。

一个非常简单明了的方法ach如下所示:

  • 您创建了一个新的
    服务
    ,该服务在后台运行,并通过套接字与服务器通信
  • 服务从套接字接收数据,并使用
    LocalBroadcastManager
  • 您的所有活动都实现了一个
    BroadcastReceiver
    ,并在
    onReceive()方法中从
    服务
    接收数据
  • 要做到这一点,你应该阅读和的介绍,了解它们是如何工作的。此外,要先了解基本概况,你应该阅读可用的

    编辑,回答评论中的问题:

    您始终可以通过调用
    stopService()停止
    服务
    但是如果你不想/不需要
    服务的所有功能,你也可以做不同的事情。除了
    服务
    之外,你还可以创建一个简单的
    线程
    HandlerThread
    ,与服务器进行通信。然后从线程内部,你可以将数据转发/广播到你的Act通过使用上述技术(
    LocalBroadcastManager
    )进行ivities


    仅举一个基本结构的示例(代码未经测试):

    然后您就有了自己的活动,例如
    MyActivity1
    MyActivity2
    ,…
    MyActivityN
    。它们都注册了嵌入的
    SocketDataReceiver
    ,以接收线程发送的广播意图
    SOCKET\u数据

    onReceive()
    方法中,您可以使用标识符
    SOCKET\u data\u标识符从
    intent
    对象中提取数据

    public class MyActivity1 extends Activity
    {
        private SocketDataReceiver socketDataReceiver;
    
        @Override
        protected void onResume() {
            super.onResume();
            socketDataReceiver = new SocketDataReceiver();
            LocalBroadcastManager.getInstance(this).registerReceiver(
                    socketDataReceiver, new IntentFilter(SocketThread.SOCKET_DATA_RECEIVED));
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            LocalBroadcastManager.getInstance(this).unregisterReceiver(socketDataReceiver);
        }
    
        private class SocketDataReceiver extends BroadcastReceiver
        {
            @Override
            public void onReceive(Context context, Intent intent) {
                // intent contains your socket data,
                // get data from intent using SocketThread.SOCKET_DATA_IDENTIFIER
            }
        }
    }
    

    这似乎正是我所需要的。我将阅读所有这三件事。但我有一个问题。我需要服务还是线程呢?据我所知,当应用程序关闭时,服务将继续运行。我不需要这样做。只有当应用程序被使用时,我才需要显示信息。好的,给我一点时间t编辑我的答案以向您提供更多信息更新了答案,并提供了一个示例以帮助您入门,这对您很有帮助。谢谢:DJust一件事。这适用于任何其他在该线程结束的人。在该示例中,在发送部分,在初始化意图时,您必须将套接字\u数据\u接收字符串传递给cons好吧,不知怎么的。我想我的建议更进一步了,抽象出你的代码是如何与服务交互的。算了吧。你永远也做不到这一点。用一个线程读取套接字,让它把它的工作分派到你喜欢的任何线程/线程池/线程工作者系统
    public class MyActivity1 extends Activity
    {
        private SocketDataReceiver socketDataReceiver;
    
        @Override
        protected void onResume() {
            super.onResume();
            socketDataReceiver = new SocketDataReceiver();
            LocalBroadcastManager.getInstance(this).registerReceiver(
                    socketDataReceiver, new IntentFilter(SocketThread.SOCKET_DATA_RECEIVED));
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            LocalBroadcastManager.getInstance(this).unregisterReceiver(socketDataReceiver);
        }
    
        private class SocketDataReceiver extends BroadcastReceiver
        {
            @Override
            public void onReceive(Context context, Intent intent) {
                // intent contains your socket data,
                // get data from intent using SocketThread.SOCKET_DATA_IDENTIFIER
            }
        }
    }