取消长轮询循环的并发问题 - java

我有一个问题,希望我可以通过写此问题来解决,但如果没有,我将发布并查看是否有人可以提供帮助。

我正在使用客户端库(我感觉写得不好)与实时聊天服务器进行交互,该服务器利用基于HTTP的COMET样式长轮询。在某些情况下,我在取消长轮询时遇到问题,并怀疑我可能需要添加一些并发处理代码,但是由于以下原因,我发现很难找到最佳方法来做到这一点。

订阅代码(用于启动长轮询)被实现为一个大循环,其中包含以下内容

doLongPoll()
{
    while(true)
    }
        //IF channel field boolean unsubscribe == TRUE, if so BREAK;
        //perform GET request (and store channel HTTPClient used for this call)
        //remove HTTPClient used for this call
        //IF channel field boolean unsubscribe == true, if so BREAK;
        //IF connection problem sleep(1500) then CONTINUE
        //post received data to listeners
    }
}

取消订阅调用(将在另一个线程上调用)

unsubscribe()
{
    //set channel field boolean unsubscribe == FALSE
    //get channel HTTPClient and shutdown
}

我已经隔离了操作交错的问题案例。对我来说,这似乎是代码是多线程的,而客户端代码不是线程安全的。管理不善和不重新使用httpClient也无济于事。

我遇到的问题之一是,取消订阅调用不会阻止下一个getRequest的发生。

THREAD 1 (polling)                      THREAD 2
--------                                --------
do unsubscribe check (pass)
                                        unsubscribe called
                                        set unsubscribe = true
                                        check if httpClient saved (none)
perform getRequest (save HttpClient first)

我想知道人们认为解决此问题的最佳方法是什么(时间也很有限,所以我不能重写太多代码!)

为了解决这个问题,我认为我可以使用同步块,从线程1的第一次取消订阅检查到httpClient保存到执行实际的get请求之前,并使用相同的锁同步unsubscribe方法。目前,这是不切实际的,因为提到的第一个同步块将在一个方法调用中开始,并在方法调用链中进一步结束(由于lib的编写方式)-感觉非常错误,因此需要一些重构。

或者,我可以只为每个通道创建一个单个httpClient,而不是为每个请求创建一个,然后就可以始终将其关闭,并且可能会忽略同步(我认为)。

或者如下所示,我可以出于相同的目的使用中断

任何建议都将受到欢迎-如果有任何进展,我会进行编辑!

谢谢

参考方案

由于这个问题,我买了Java Concurrency in Practice,发现他们在的第7章:取消和关闭中讨论了与此类似的问题,可以通过引用对其进行总结。

中断通常是最成功的实现方式
消除

由于HttpClient阻止了不支持中断的套接字IO,因此我有两种方法。我分配了httpClient,在实际httpClient.execute()调用之前检查中断,并在unsubscribe()方法中中断线程,然后调用httpClient.getConnectionManager().shutdown();。这似乎解决了我的问题,并且是一个非常简单的更改。没有更多的交错问题!

我还按照建议将boolean unsubscribe字段设置为volatile,这是我之前应该做的-仅此一项并不能解决问题

绑定Java库Xamarin.Android - java

我花了两天时间在每个论坛,文档,tuto,博客等上寻找答案。我为实习生启动了一个Android应用程序,因为我不懂Java,所以用xamarin C#开发了它。直到最近一切都还不错,但现在我需要集成一个SDK才能在应用程序中使用POS(销售点),但是该库是用Java编写的,即使跟随文档或辅导老师,我也无法将其与xamarin绑定(我什至无法调试)。这里有人已…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…