`
lvhuiqing
  • 浏览: 244435 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

1.2. Benefits of Threads(线程的好处)

阅读更多
1.2. Benefits of Threads(线程的好处)
When used properly, threads can reduce development and maintenance costs and improve the performance of complex applications. Threads make it easier to model how humans work and interact, by turning asynchronous workflows into mostly sequential ones. They can also turn otherwise convoluted code into straight-line code that is easier to write, read, and maintain.
如果使用得当,线程可以降低开发和维护的成本,并且可以加快复杂应用的执行性能。线程的通过最大程度的把可以异步分解的工作流分割成顺序执行的工作,更为容易的实现了对人类活动和交互建模。线程也同时实现了把难以实现繁杂的代码变成通俗易懂的代码,以便于编码、阅读和维护。
Threads are useful in GUI applications for improving the responsiveness of the user interface, and in server applications for improving resource utilization and throughput. They also simplify the implementation of the JVM the garbage collector usually runs in one or more dedicated threads. Most nontrivial Java applications rely to some degree on threads for their organization.
在GUI程序中,线程被用来实现更好的用户界面响应性。在服务器上,则被用来实现更好的资源利用和达到更大的吞吐量。线程同样简化了jvm垃圾回收机制的实现-通常是运行一个或多个专注于垃圾回收的线程来实现。大部分优秀的java应用程序都在一定程度上依赖于线程的使用。
1.2.1. Exploiting Multiple Processors(充分利用多处理器)
Multiprocessor systems used to be expensive and rare, found only in large data centers and scientific computing facilities. Today they are cheap and plentiful; even low-end server and midrange desktop systems often have multiple processors. This trend will only accelerate; as it gets harder to scale up clock rates, processor manufacturers will instead put more processor cores on a single chip. All the major chip manufacturers have begun this transition, and we are already seeing machines with dramatically higher processor counts.
多核处理器曾经是非常昂贵的,通常仅仅在大型数据中心和科学计算机构才能够见到。但是现在这样的处理器已经“飞入寻常百姓家”,低端的服务器、中等配置的桌面系统都拥有多个处理器。这种趋势还会加速进行,因为cpu速率的数量级级别的提升已经变得越来越困难。因此cpu的制造厂商开始趋向于在同一块主板上集成更多的cup核。所有主要的主板厂商已经开始应对这种趋势,他们预见到了处理器数量的急剧增加。
Since the basic unit of scheduling is the thread, a program with only one thread can run on at most one processor at a time. On a two-processor system, a single-threaded program is giving up access to half the available CPU resources; on a 100-processor system, it is giving up access to 99%. On the other hand, programs with multiple active threads can execute simultaneously on multiple processors. When properly designed, multithreaded programs can improve throughput by utilizing available processor resources more effectively.
Cpu基本的调度单位是线程,这就意味着如果一个程序内部如果只有一个线程那么这个程序在同一时间只能在一个处理器上运行。在一个双处理器的系统上,一个单线程的程序意味着放弃了一半的cpu资源。在一个100cpu的系统上,则意味着放弃了99%。另一方面,拥有多个活动线程的程序则可以同时在多个处理器上运行。如果设计得当,这些多线程程序可以通过更有效率的使用cpu资源来得到更好的吞吐率。
Using multiple threads can also help achieve better throughput on single processor systems. If a program is single-threaded, the processor remains idle while it waits for a synchronous I/O operation to complete. In a multithreaded program, another thread can still run while the first thread is waiting for the I/O to complete, allowing the application to still make progress during the blocking I/O. (This is like reading the newspaper while waiting for the water to boil, rather than waiting for the water to boil before starting to read.)
在单个cpu系统中,使用多线程程序同样可以达到提供吞吐率的可能。如果一个程序是单线程的,处理器在等待同步IO操作完成的时候会处于空闲状态,而多线程程序此时则可以安排另外一个线程来利用这些空闲时间(这一点与在水沸腾之前看会儿报纸是同样的道理)。
1.2.2. Simplicity of Modeling(易于建模)
It is often easier to manage your time when you have only one type of task to perform (fix these twelve bugs) than when you have several (fix the bugs, interview replacement candidates for the system administrator, complete your team's performance evaluations, and create the slides for your presentation next week). When you have only one type of task to do, you can start at the top of the pile and keep working until the pile is exhausted (or you are); you don't have to spend any mental energy figuring out what to work on next. On the other hand, managing multiple priorities and deadlines and switching from task to task usually carries some overhead.
通常在一个人只有同一种任务的情况下(比如修改12个bug),管理自己的时间是比较容易的。而在处理多个任务的情况下,管理时间变得相对困难(比如修改bug,面试系统管理员的应聘者,完成团队的性能评估,为下周的演示做幻灯片)。当你只有种类型的工作去做的时候,亦可以在管道的顶端开始,然后一直工作,直到管道被耗尽(当然也有可能是你被耗尽,呵呵)。你不必为去想下一步该做什么而费神。在另一方面,管理任务的优先级、任务的生命周期、任务与任务之间的切换通常带来很大的额外开销。
The same is true for software: a program that processes one type of task sequentially is simpler to write, less error-prone, and easier to test than one managing multiple different types of tasks at once. Assigning a thread to each type of task or to each element in a simulation affords the illusion of sequentiality and insulates domain logic from the details of scheduling, interleaved operations, asynchronous I/O, and resource waits. A complicated, asynchronous workflow can be decomposed into a number of simpler, synchronous workflows each running in a separate thread, interacting only with each other at specific synchronization points.
对于软件来说,情况同样如此。比起在一个程序成做多个任务,一个程序完成同类型的可顺序执行的任务的编程模式通常是易于编码、不易出错而且是易于测试的。为每一种特定类型的任务或者每一个虚拟元素安排一个线程,从而避免顺序执行所带来的混乱,并能够把领域逻辑从调度细节、存取操作、异步IO以及资源等待中抽取出来。一个复杂的异步的工作流可以被分解成几个简单的,同步的工作流,每个工作流运行在一个单独的线程中,只是在某些特定的同步点上进行交互。
This benefit is often exploited by frameworks such as servlets or RMI (Remote Method Invocation). The framework handles the details of request management, thread creation, and load balancing, dispatching portions of the request handling to the appropriate application component at the appropriate point in the work-flow. Servlet writers do not need to worry about how many other requests are being processed at the same time or whether the socket input and output streams block; when a servlet's service method is called in response to a web request, it can process the request synchronously as if it were a single-threaded program. This can simplify component development and reduce the learning curve for using such frameworks.
这种优势通常会被框架所采用,比如servlet、RMI。这些框架会处理诸如请求管理、线程创建、负载均衡等细节,并且把工作六中同一请求的不同部分转发给恰当处理模块。Servlet的编写者不必关心在同一时间内有多少个请求会被同时处理,也不必关心socket的输入流输出流的任何细节。当一个servlet的service方法被执行来响应web请求的时候,程序可以同步的处理一个请求,就好像这是一个单线程的程序。这可以简化组件的开发,并且降低使用这些框架的学习曲线。
1.2.3. Simplified Handling of Asynchronous Events(简化异步事务的处理)
A server application that accepts socket connections from multiple remote clients may be easier to develop when each connection is allocated its own thread and allowed to use synchronous I/O.
一个用来从不同的远程客户端上接受socket连接的服务器应用程序是容易开发的,如果使用同步IO,为每一个连接分配自己的线程。
If an application goes to read from a socket when no data is available, read blocks until some data is available. In a single-threaded application, this means that not only does processing the corresponding request stall, but processing of all requests stalls while the single thread is blocked. To avoid this problem, single threaded server applications are forced to use nonblocking I/O, which is far more complicated and error-prone than synchronous I/O. However, if each request has its own thread, then blocking does not affect the processing of other requests.
如果一个应用想从一个socket上读取字节,在没有数据的情况下,读取方法会被阻塞直到有新的数据到来。在一个单线程应用程序中,这种阻塞不仅仅意味着相应的请求处理会被会被拖延,所有的请求都会被拖延。为了避免出现这样的问题,单线程服务器应用程序被强制使用非阻塞IO。这种IO机制远比同步IO复杂,并且更容易潜藏错误。但是如果每一个请求都拥有自己单独的线程,那么阻塞就不会影响其他线程的处理效率。
Historically, operating systems placed relatively low limits on the number of threads that a process could create, as few as several hundred (or even less). As a result, operating systems developed efficient facilities for multiplexed I/O, such as the Unix select and poll system calls, and to access these facilities, the Java class libraries acquired a set of packages (java.nio) for nonblocking I/O. However, operating system support for larger numbers of threads has improved significantly, making the thread-per-client model practical even for large numbers of clients on some platforms. [1]
在过去,操作系统会对相关的一个进程可以创建的相关的低级别的线程的线程数量进行限制,通常会限制成几百个或者更少。因此,操作系统实现了高效的多路复用的IO机制,例如Unix操作系统的select和poll机制。为了访问这样的机制,java中引入了nio类库。但是现代操作系统对线程数量的支持已经在很大程度上加大了,这就使得每一个客户端一个线程的模式在支持大数量客户端的平台上变得使用

[1] The NPTL threads package, now part of most Linux distributions, was designed to support hundreds of thousands of threads. Nonblocking I/O has its own benefits, but better OS support for threads means that there are fewer situations for which it is essential.
NPTL线程包,目前大多数linux版本的一部分,是被设计用来支持成千上万的线程的。非阻塞的IO拥有其自身的优势,但是随着操作系统对线程的良好支持,NIO是必不可少的情况已经变得越来越少了。
1.2.4. More Responsive User Interfaces(反映良好的用户界面)
GUI applications used to be single-threaded, which meant that you had to either frequently poll throughout the code for input events (which is messy and intrusive) or execute all application code indirectly through a "main event loop". If code called from the main event loop takes too long to execute, the user interface appears to "freeze" until that code finishes, because subsequent user interface events cannot be processed until control is returned to the main event loop.
GUI程序曾经是单线程工作的,这就意味着你要么必须频繁的轮换的执行针对输入时间的代码或者在一个main loop中执行所有的程序代码。如果main loop中的代码调用很长的话,因为后面的用户界面时间不能被执行,用户界面会变得好像被“冻结”一样,直到代码被执行结束。
Modern GUI frameworks, such as the AWT and Swing toolkits, replace the main event loop with an event dispatch thread (EDT). When a user interface event such as a button press occurs, application-defined event handlers are called in the event thread. Most GUI frameworks are single-threaded subsystems, so the main event loop is effectively still present, but it runs in its own thread under the control of the GUI toolkit rather than the application.
现代的用户界面架构,例如AWT和Swing工具集,使用事件分发线程来取代主事件轮询。当一个用户界面事件发生的时候(比如按钮被按下)程序定义的时间处理程序会在事件线程中被执行。大多数的GUI架构是单线程的子系统,因此主事件轮询机制所带来的该效率仍然存在,但是这种轮询是在GUI的工具集中进行控制的而不是在应用程序中进行控制。
If only short-lived tasks execute in the event thread, the interface remains responsive since the event thread is always able to process user actions reasonably quickly. However, processing a long-running task in the event thread, such as spell-checking a large document or fetching a resource over the network, impairs responsiveness. If the user performs an action while this task is running, there is a long delay before the event thread can process or even acknowledge it. To add insult to injury, not only does the UI become unresponsive, but it is impossible to cancel the offending task even if the UI provides a cancel button because the event thread is busy and cannot handle the cancel button-press event until the lengthy task completes! If, however, the long-running task is instead executed in a separate thread, the event thread remains free to process UI events, making the UI more responsive.
如果只有短期的任务在事件线程中执行,那么用户界面依然是可交互的而且事件线程一直可以快速响应用户动作。然后,如果要在事件线程中处理一个长时间的任务,例如对一个大文件进行拼写检查,或者从网络上获取一个资源,就会虚弱响应的迅速性。如果任务正在运行的时候,用户执行了一个操作,那么在事件线程处理该事件之前甚至是响应之前就有一个比较长的延迟。但是更为糟糕的是,不仅仅用户
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics