本文共 2578 字,大约阅读时间需要 8 分钟。
在编程中,同步与异步、堵塞与非堵塞是常见的概念,但它们之间存在着一些混淆。我们需要从根本上理解它们的区别以及如何在实际开发中应用。
同步编程是指在发出一个功能调用时,当前线程会一直等待,直到该函数或操作完成之前,该调用才会返回。这种方式在单线程环境下非常常见,尤其是在需要确保数据一致性的场景中。
在Android中,UI线程的不安全性使得我们通常需要使用同步机制。例如,通过handler.SendMessage函数实现同步线程传递数据。这种方式确保了数据能够及时传递给目标窗体,但也需要注意避免在主线程中进行长时间的同步操作,以免阻塞UI线程。
异步编程则相反。它允许调用者立即返回,而不必等待结果。结果通过回调、监听者模式或观察者模式等方式在后续操作中传递。这在需要处理长时间任务或对UI线程不影响的场景中非常有用。
Android中的AsyncTask类就是一个典型的异步编程工具,它允许在后台线程执行长时间任务,并在任务完成后通过回调将结果传递给UI线程。
堵塞和非堵塞则描述了线程的状态:
需要注意的是,堵塞并不一定意味着同步。例如,在网络编程中,Receive函数可能会堵塞当前线程,直到数据到达,但其他线程仍然可以继续执行。
通过买票的案例可以更直观地理解同步与异步的区别:
java.net.InetSocketAddressInetSocketAddress是一个实现IP套接字地址的类。它可以表示为IP地址加端口号,或者主机名加端口号。在解析主机名失败的情况下,它仍然可以作为未解析地址使用。
java.nio.channels.Selector选择器用于管理多个通道的I/O操作。通过选择器,可以在单线程内同时监控多个通道的读写状态。这对于处理大量连接非常有用。
java.nio.channels.SocketChannelSocketChannel是Java NIO中用于处理流连接的通道。它支持非堵塞连接和异步关闭,适合在网络编程中高效地处理数据传输。
以下是连接服务器并处理数据的完整代码示例:
Selector mSelector = null;SocketChannel client = null;InetSocketAddress isa = null;SocketEventListener mSocketEventListener = null;private boolean connect(String site, int port) { if (mSocketEventListener != null) { mSocketEventListener.onSocketPause(); } boolean ret = false; try { mSelector = Selector.open(); client = SocketChannel.open(); client.socket().setSoTimeout(5000); isa = new InetSocketAddress(site, port); boolean isConnect = client.connect(isa); if (!isConnect) { while (!client.finishConnect()) { EngineLog.redLog(TAG, "等待非堵塞连接建立...."); Thread.sleep(50); if (waittimes < 100) { waittimes++; } else { break; } } } Thread.sleep(500); haveRepaired(); startListener(); ret = true; } catch (Exception e) { EngineLog.redLog(TAG + " - Connect error", e != null ? e.toString() : "null"); try { Thread.sleep(1000 * 10); } catch (Exception e1) { EngineLog.redLog(TAG + " - Connect error", e1 != null ? e1.toString() : "null"); } ret = false; } return ret;} 在关闭套接字通道时,需要注意以下几点:
interrupt方法中断正在堵塞的线程。通过理解同步与异步的本质,以及掌握Java NIO中的一些核心类,我们可以更高效地进行网络编程。在实际开发中,选择合适的编程模型(同步或异步)以及正确使用相关API,是确保程序高效稳定运行的关键。
转载地址:http://hshfk.baihongyu.com/