我的应用程序具有用于用户交互的 Activity 和后台服务,这是唯一修改数据模型的地方。后台服务监听用户执行的操作以及来自网络的传入消息。因此可能会出现并发问题,我试图通过使用处理程序来防止这些问题。 对于事件层,我使用 greenrobots Eventbus。
这一切都运行良好,但我想知道是否有更智能/更快/代码更少(因此更不容易出错)的方式来处理这个用例?
更具体地说:
这是我的方法:
在 oncreate 方法中,我会注册服务(如果有 Activity ,我会在 onstart 中执行此操作)
@Override
public void onCreate() {
super.onCreate();
...
EventBus.getDefault().register(this);
}
在 onDestroy 中,我再次注销:
@Override
public void onDestroy() {
super.onDestroy();
....
EventBus.getDefault().unregister(this);
}
每当我对传入事件使用react时,我都想确保串行执行,因为可能会出现并发问题,因为存在来自用户交互以及通过网络来自其他用户的传入事件。所以我决定使用处理程序:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Object receivedEvent = msg.obj;
if(receivedEvent instanceof EditUser)
{
processEditUserBroadcast((EditUser)receivedEvent);
}
else if(receivedEvent instanceof JoinParty)
{
processJoinPartyBroadcast((JoinParty)receivedEvent);
}
else if(receivedEvent instanceof LeaveParty)
{
processLeavePartyBroadcast();
}
else if(receivedEvent instanceof SendMessage)
{
processSendMessageBroadcast((SendMessage)receivedEvent);
}
else if(receivedEvent instanceof ReceivedMessage)
{
processReceivedMessageBroadcast((ReceivedMessage)receivedEvent);
}
else if(receivedEvent instanceof Reset)
{
processResetBroadcast();
}
else if(receivedEvent instanceof ImageDownloadFinished)
{
processImageDownloadFinishedBroadcast((ImageDownloadFinished)receivedEvent);
}
}
};
return handler;
}
对于每个感兴趣的事件,我都有一个 onEvent 方法,它只是将事件传递给处理程序,以确保通过一个小的“passToHandler”辅助函数串行执行
public void passToHandler(Handler handler, Object object)
{
Message message = handler.obtainMessage();
message.obj = object;
handler.sendMessage(message);
}
public void onEvent(EditUser editUser)
{
passToHandler(handler,editUser);
}
public void onEvent(JoinParty joinParty)
{
passToHandler(handler,joinParty);
}
public void onEvent(LeaveParty leaveParty)
{
passToHandler(handler,leaveParty);
}
public void onEvent(SendMessage sendMessage)
{
passToHandler(handler,sendMessage);
}
public void onEvent(ReceivedMessage receivedMessage)
{
passToHandler(handler,receivedMessage);
}
public void onEvent(Reset reset)
{
passToHandler(handler,reset);
}
public void onEvent(ImageDownloadFinished imageDownloadFinished)
{
passToHandler(handler,imageDownloadFinished);
}
“过程..”方法是“数据魔法”发生的地方,不应该与我的问题相关。
当然,对于每个可能发生的事件,我确实创建了一个类,它通常像这样非常 slim :
public class JoinParty {
private String partyCode;
public JoinParty(String partyCode) {
super();
this.partyCode = partyCode;
}
public String getPartyCode() {
return partyCode;
}
}
最佳答案
感谢您发布此 Matthias!我认为您提出了关于 GreenRobot EventBus 的线程安全的一个非常重要的观点,它的用户很容易忽略这一点。
虽然我是 GreenRobot EventBus 和 Android(但不是 Java)的新手,但我认为您很可能正朝着正确的方向前进。如果我正确阅读了 GreenRobot EventBus 源代码,这种方法的另一个可能的好处是将 SendMessage 事件发布到您的 onEvent() 方法会立即返回(在处理程序上调用 sendMessage 之后),从而允许 EventBus 继续将其发布到任何其他订阅者,而不会延迟您类(class)的实际处理。不过,这可能是您想要的,也可能不是。
使用您提供的方法,您需要确保的另一件事是,如果您采用这样的方法,则您的类没有其他公共(public)方法具有您的所有 onEvent() 方法和方法作为 processEditUserBroadcast()。否则,虽然您已确保从 EventBus 接收到的事件的所有处理实际上都在单个线程上处理(以串行方式),但其他一些类可能会在不同的线程上调用此类的公共(public)方法,然后导致你又遇到安全问题了。
如果您知道您确实需要在此类上支持其他公共(public)方法,那么按照您在此处所做的操作至少将所有 onEvent() 方法处理到单个线程(创建线程的 Looper 的线程) Looper 从我在 Looper 类的文档中读到),这至少简化了一些事情。然后,您可能还需要对公共(public)方法和所有其他方法(例如 processEditUserBroadcast())应用一些同步,以确保在您要使用其他公共(public)方法时从多个线程安全访问该类的数据成员这节课。或者,根据这些数据成员是什么以及您的需求,您可以简单地使其中一些成为 volatile 、原子性或使用并发集合等。这完全取决于读写访问权限需求是这些访问所需的粒度。
这有帮助吗?对于那些精通 Android、Loopers、Handlers、GreenRobot EventBus 等的人,我有没有说错?
关于android - 具有线程安全性的事件总线的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27793763/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?