作者:empty 出版社:empty |
什么是线程?几乎每种操作系统都支持进程的概念—进程就是在某种程度上相互隔离的、独立运行的程序,线程化是允许多个活动共存于个进程中的工具。大多数现代的操作系统都支持线程,而且线程的概念以各种形式已存在了好多年, Java是第一个在语言本身中显式地包含线程的主流编程语言, 它没有把线程化看作是底层操作系统的工具,有时候,线程也称作轻量级进程。就象进程样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而H它们从同一堆中分配对象,尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。Java线程工具和API看似简单, 但是, 编写有效使用线程的复杂程序并不十分容易。因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰,每个Java程序都使用线程每个Java程序都至少有一个线程一主线程。当一个Java程序启动时, JVM会创建主线程, 井在该线程中调用程序的main() 方法,JVM还创建了其它线程, 您通常都看不到它们一例如, 与垃圾收集、对象终止和其它JM内务处理任务相关的线程。其它工具也创建线程, 如AW(抽象窗工具箱(Abstract Wnd owing Toolkit) )或Swing U工具箱、servlet容器、应用程序服务器和RM(远程方法调用(Re note Mt hodInvocation) ) 。为什么使用线程?在Java程序中使用线程有许多原因.如果您使用Swing、servlet、RM或Enterprise JavaBeans(EJB) 技术, 您也许没有意识到您已经在使用线程了。使用线程的一些原因是它们可以帮助:响应更快的UI事件驱动的U工具箱《如AW和Swing) 有一个事件线程, 它处理U事件, 如击键或鼠标点击。AW和Swing程序把事件侦听器与U对象连接。当特定事件(如单击了某个按钮) 发生时, 这些侦听器会得到通知。事件侦听器是在AW事件线程中调用的。如果事件侦听器要执行持续很久的任务,如检查一个大文档中的拼写,事件线程将忙于运行拼写检查器,所以在完成事件似听器之前,就不能处理额外的U事件,这就会使程序看来似乎停滞了,让用户不知所扑。要避免使U延迟响应,事件侦听器应该把较长的任务放到另个线程中,这样AW线程在任务的执行过程中就可以继续处理U事件(包括取消正在执行的长时间运行任务的请求),利用多处理器系统多处理器(MP)系统比过去更普及了,以前只能在大型数据中心和科学计算设施中才能找到它们。现在许多低端服务器系统一甚至是一些台式机系统一都有多个处理器,现代操作系统, 包括Linux、Solaris和Wn do wsN/2000.都可以利用多个处理器并调度线程在任何可用的处理器上执行,
调度的基本单位通常是线程:如果某个程序只有个活动的线程,它次只能在个处理器上运行.如果某个程序有多个活动线程,那么可以同时调度多个线程,在精心设计的程序中,使用多个线程可以提高程序春吐量和性能。简化建模在某些情况下,使用线程可以使程序编写和维护起来更简单,考虑一个仿真应用程序,您要在其中模拟多个实体之间的交互作用。给每个实体一个自己的线程可以使许多仿真和对应用程序的建模大大简化。另一个适合使用单独线程来简化程序的示例是在一个应用程序有多个独立的事件驱动的组作的时候。例如,一个应用程序可能有这样一个组件,该组件在某个事件之后用秒数倒计时,并更新屏幕显示,与其让一个主循环定期检查时间并更新显示,不如让一个线程什么也不做,一直休眠,直到某一段时间后,更新屏幕上的计数器,这样更简单,而且不容易川错.这样。主线程就根本无需担心计时器。异步或后台处理服务器应用程序从远程来源(如套接字)获取输入,当读取套接字时,如果当前没有可用数据,那么对Socket InputStream read() 的调用将会阻塞, 直到有可用数据为止。如果单线程程序要读取套接字,而套接字另一端的实体并未发送任何数据,那么该程序只会永远等待,而不执行其它处理。相反,程序可以轮询套接字,查看是否有可用数据,但通常不会使用这种做法,因为会影响性能,但是,如果您创建了一个线程来读取套接字,那么当这个线程等待套接字中的输入时,主线程就可以执行其它任务。您甚至可以创建多个线程,这样就可以同时读取多个套接字,这样,当有可用数据时,您会迅速得到通知(因为正在等待的线程被唤醒),而不必经常轮询以检查是否有可用数据。使用线程等待套接字的代码也比轮询更简单、更不易出错.爱好者简单,但有时有风险虽然Java线程工具非常易于使用, 但当您创建多线程程序时, 应该尽量避免一些风险,当多个线程访问同一数据项(如静态字段、可全局访问对象的实例字段或共享集合)时,需要确保它们协调了对数据的访问,这样它们都可以看到数据的一致视图,而且相互不会干扰另一方的更改。为了实现这个目的, Java语言提供了两个关键字; synchronized和volatile。我们将稍后在本教程中研究这些关键字的用途和意义。当从多个线程中访问变量时,必须确保对该访问正确地进行了同步。对于简单变量,将变量声明成volatile也许就足够了, 但在大多数情况下, 需要使用同步。如果您将要使用同步来保护对共享变量的访问,那么必须确保在程序中所有访问该变量的地方都使用同步。不要做过头虽然线程可以大大简化许多类型的应用程序,过度使用线程可能会危及程序的性能及其可维护性,线程消耗了资源。因此,在不降低性能的情况下,可以创建的线程的数量是有限制的。尤其在单处理器系统中, 使用多个线程不会使主要消耗CPU资源的程序运行得更快。示例:使用一个线程用于计时,并使用另一个线程完成工作