[英]Multiple threads reading from same socket
我正在开发一个显示服务器数据的应用程序。 服务器不是我的,它不是很稳定。 连接太多会导致服务器崩溃。
我在主要活动中有一个到服务器的套接字,但有时我想打开读取数据并显示它的子活动。 我的问题是我无法使用相同的套接字实现此功能,并且必须为每个活动打开一个新套接字。 每个活动都有一个线程,它从套接字读取并根据需要更新该活动的UI元素。
为了在多个活动中使用相同的套接字,我尝试在开始新活动之前关闭活动的inputReader,但这只是让应用程序挂起。 如果我将其保持打开状态,则新活动中的新线程永远不会收到任何数据。 在开始新活动之前杀死线程是不可能的,因为线程通常被read()函数阻止。
无论如何我有一个集中的线程来执行读取,然后将数据发送到其他活动中的所有其他线程,这样我就不必在每个活动中打开新的套接字了吗?
我觉得这是我要问的一个非常基本的问题,但我无法找到解决方案。
基本上你自己回答了你的问题:
我可以有一个集中的线程来执行读取,然后将数据发送到其他活动中的所有其他线程。
意义:当然,这样的事情是可能的。 但你必须坐下来,设计并实施它。 您首先要定义一个合理的接口,允许您的其他线程与该中央服务进行通信 ,例如:
enum RequestType { DO_THIS, DO_THAT };
interface ServerConnectionService<T> {
List<T> performRequest(RequestType request);
}
含义:不是让你的不同线程在该套接字上进行“低级别”交谈,而是创建一个抽象,允许你说:“当我需要这种信息时,我会使用我的服务;它会返回一些特定的答案当然,这是一个非常通用的答案,但是,你的问题也不完全具体。
接下来的步骤是对该接口进行一些中心(可能是单例)实现; 它在自己的线程上运行,并且可以由其他线程以同步的,明确定义的方式使用。
最后的警告:如果您没有该服务器,并且它质量低并且给您带来麻烦 - 这不是一个好的设置。 因为无论你在代码中做了什么,如果服务器做得不好,用户就会认为你的应用程序是问题所在。 由于某些远程服务器崩溃,用户不关心操作是否失败。 所以你问题的另一个方面是:现在,你处在一个不好的地方。 你应该花一些时间来寻找出路。 否则,您将浪费大量时间为您正在处理的服务器构建变通方法。
一个非常简单明了的方法如下:
Service
Service
从套接字接收数据并通过使用LocalBroadcastManager
将其转发/广播到您有兴趣接收它的所有活动(例如更新UI) BroadcastReceiver
并在onReceive()
方法中从您的Service
接收数据 要实现这一点,您应该阅读Services和BroadcastReceivers的介绍,以了解它们的工作原理。 另外,为了首先获得基本概述,您应该阅读有关可用的App组件的信息 。
编辑,回答评论中的问题:
您可以随时停止Service
调用stopService()
但你也可以做到这一点不同,如果你不希望/需要的所有功能Service
。 代替的Service
,你也可以创建一个简单的Thread
或HandlerThread
与服务器communinicates。 从Thread内部,您可以使用上面提到的技术( LocalBroadcastManager
)将数据转发/广播到您的活动。
只是为了给你一个基本结构的例子(尽管代码未经测试):
class SocketThread implements Runnable
{
static final String SOCKET_DATA_RECEIVED = "com.your.package.SOCKET_DATA_RECEIVED";
static final String SOCKET_DATA_IDENTIFIER = "com.your.package.SOCKET_DATA";
private Context context;
SocketThread(Context c) {
context = c.getApplicationContext();
}
@Override
public void run() { // code running in your thread
// fetch data from socket ...
Intent intent = new Intent();
intent.putExtra(SOCKET_DATA_IDENTIFIER, data); // store data in your intent
// send data to registered receivers
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
// your code ...
}
}
然后你有你的活动,例如MyActivity1
, MyActivity2
,... MyActivityN
。 它们都注册了它们的嵌入式SocketDataReceiver
以接收由您的线程发送的广播意图SOCKET_DATA_RECEIVED
。
在onReceive()
方法中,您可以使用标识符SOCKET_DATA_IDENTIFIER
从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
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.