我正在开发一款Android应用,其中应用与我的服务器之间会有很多网络通信。
要完成此操作,我使用SocketChannel
和Selector
来执行非阻塞IO。
我选择的设计是,将有一个BlockingQueue
“NetworkIOManager”线程将在其上等待。该应用程序的其他线程将向BlockingQueue
发送消息,NetworkIOManager
将拾取这些消息并将其发送到另一个线程AsyncRequestHandlerThread
。
因此NetworkIOManager
主题的主要职责是从BlockingQueue
中选择邮件并将其委托给AsyncRequestHandlerThread
发送请求并接收回复。
NetworkIOManager.java
的代码:
public class NetworkIOManager implements Runnable
{
private AsyncRequestHandlerThread handlerThread = null;
/*
*
* some code here
*
*/
private void vSendRequestUsingSocketChannel(String pTargetURL, int pTargetPort, String pRequestXML, boolean pUseSameConn) {
// if thread is not created, initialize the thread
if(handlerThread == null) {
handlerThread = new AsyncRequestHandlerThread();
}
// create a channel to send the request and register it with the selector
AsyncRequestHandlerThread.createChannelWithSelector(pTargetURL, pTargetPort, pRequestXML);
// if thread is not started, start it.
if(!handlerThread.isAlive())
handlerThread.start();
}
}
AsyncRequestHandlerThread
基本上为每个要发送的请求创建SocketChannel
,并使用Non-Blocking
配置并将其注册为与此线程关联的单个Selector
。
AsyncRequestHandlerThread.java
的代码:
public class AsyncRequestHandlerThread extends Thread {
private static Selector selector = null;
public AsyncRequestHandlerThread() {
if(selector == null)
vSetSelector();
}
private static void vSetSelector()
{
try {
selector = Selector.open();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static Selector getSelector()
{
return selector;
}
public static void createChannelWithSelector(String pTargetURL, int pTargetPort, String pRequestXML) {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(pTargetURL, pTargetPort));
socketChannel.register(selector, SelectionKey.OP_CONNECT, pRequestXML);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
// Wait for events with TIMEOUT : 30 secs
while (selector.select(30000) > 0) {
try {
// Get list of selection keys with pending events
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
// Process each key at a time
while (iterator.hasNext()) {
// Get the selection key
SelectionKey selKey = (SelectionKey)iterator.next();
// Remove it from the list to indicate that it is being processed
iterator.remove();
if (selKey.isValid() && selKey.isConnectable()) {
// Get channel with connection request
SocketChannel sChannel = (SocketChannel)selKey.channel();
boolean success = sChannel.finishConnect();
if (success) {
sChannel.register(selector, SelectionKey.OP_WRITE, selKey.attachment());
}
else {
// An error occurred; handle it
// Unregister the channel with this selector
selKey.cancel();
}
}
else if(selKey.isValid() && selKey.isWritable()) {
SocketChannel sChannel = (SocketChannel)selKey.channel();
// See Writing to a SocketChannel
ByteBuffer requestBuffer = null;
requestBuffer = ByteBuffer.wrap(selKey.attachment().toString().getBytes(Charset.forName("UTF-8")));
sChannel.write(requestBuffer);
sChannel.register(selector, SelectionKey.OP_READ);
}
else if (selKey.isValid() && selKey.isReadable()) {
// Get channel with bytes to read
SocketChannel sChannel = (SocketChannel)selKey.channel();
// See Reading from a SocketChannel
ByteBuffer responseBuffer = ByteBuffer.allocate(15);
while(sChannel.read(responseBuffer) > 0) {
String responseString = new String(responseBuffer.array(), Charset.forName("UTF-8"));
Log.d("STATS", responseString);
}
sChannel.close();
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(CancelledKeyException e) {
e.printStackTrace();
}
}
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}
我面临的问题是当我在设备上运行应用程序时,我在类java.lang.IllegalThreadStateException
的行handlerThread.start();
上遇到异常NetworkIOManager
。当我调试它时,应用程序工作正常。
我无法理解问题所在,以及如何解决?
有什么建议吗?
答案 0 :(得分:1)
您尝试在退出后尝试启动该主题。你需要重新思考你的逻辑。它目前假设只有一个这样的线程并且它永远不会退出,这是不正确的。