一、线程概述
线程是程序运行的基本执行单元。当操作系统(不包括单线程的操作系统,如微软早期的DOS)在执行一个程序时,会在系统中建立一个进程,而在这个进程中,必须至少建立一个线程(这个线程被称为主线程)来作为这个程序运行的入口点。因此,在操作系统中运行的任何程序都至少有一个主线程。
进程和线程是现代操作系统中两个必不可少的运行模型。在操作系统中可以有多个进程,这些进程包括系统进程(由操作系统内部建立的进程)和用户进程(由用户程序建立的进程);一个进程中可以有一个或多个线程。进程和进程之间不共享内存,也就是说系统中的进程是在各自独立的内存空间中运行的。而一个进程中的线可以共享系统分派给这个进程的内存空间。
线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈, 是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。
注意:任何一个线程在建立时都会执行一个函数,这个函数叫做线程执行函数。也可以将这个函数看做线程的入口点(类似于程序中的main函数)。无论使用什么语言或技术来建立线程,都必须执行这个函数(这个函数的表现形式可能不一样,但都会有一个这样的函数)。如在Windows中用于建立线程的API函数CreateThread的第三个参数就是这个执行函数的指针。
在操作系统将进程分成多个线程后,这些线程可以在操作系统的管理下并发执行,从而大大提高了程序的运行效率。虽然线程的执行从宏观上看是多个线程同时执行,但实际上这只是操作系统的障眼法。由于一块CPU同时只能执行一条指令,因此,在拥有一块CPU的计算机上不可能同时执行两个任务。而操作系统为了能提高程序的运行效率,在一个线程空闲时会撤下这个线程,并且会让其他的线程来执行,这种方式叫做线程调度。我们之所以从表面上看是多个线程同时执行,是因为不同线程之间切换的时间非常短,而且在一般情况下切换非常频繁。假设我们有线程A和B。在运行时,可能是A执行了1毫秒后,切换到B后,B又执行了1毫秒,然后又切换到了A,A又执行1毫秒。由于1毫秒的时间对于普通人来说是很难感知的,因此,从表面看上去就象A和B同时执行一样,但实际上A和B是交替执行的。
二、线程给我们带来的好处
如果能合理地使用线程,将会减少开发和维护成本,甚至可以改善复杂应用程序的性能。如在GUI应用程序中,还以通过线程的异步特性来更好地处理事件;在应用服务器程序中可以通过建立多个线程来处理客户端的请求。线程甚至还可以简化虚拟机的实现,如Java虚拟机(JVM)的垃圾回收器(garbage collector)通常运行在一个或多个线程中。因此,使用线程将会从以下五个方面来改善我们的应用程序:
1. 充分利用CPU资源
现在世界上大多数计算机只有一块CPU。因此,充分利用CPU资源显得尤为重要。当执行单线程程序时,由于在程序发生阻塞时CPU可能会处于空闲状态。这将造成大量的计算资源的浪费。而在程序中使用多线程可以在某一个线程处于休眠或阻塞时,而CPU又恰好处于空闲状态时来运行其他的线程。这样CPU就很难有空闲的时候。因此,CPU资源就得到了充分地利用。
2. 简化编程模型
如果程序只完成一项任务,那只要写一个单线程的程序,并且按着执行这个任务的步骤编写代码即可。但要完成多项任务,如果还使用单线程的话,那就得在在程序中判断每项任务是否应该执行以及什么时候执行。如显示一个时钟的时、分、秒三个指针。使用单线程就得在循环中逐一判断这三个指针的转动时间和角度。如果使用三个线程分另来处理这三个指针的显示,那么对于每个线程来说就是指行一个单独的任务。这样有助于开发人员对程序的理解和维护。
3. 简化异步事件的处理
当一个服务器应用程序在接收不同的客户端连接时最简单地处理方法就是为每一个客户端连接建立一个线程。然后监听线程仍然负责监听来自客户端的请求。如果这种应用程序采用单线程来处理,当监听线程接收到一个客户端请求后,开始读取客户端发来的数据,在读完数据后,read方法处于阻塞状态,也就是说,这个线程将无法再监听客户端请求了。而要想在单线程中处理多个客户端请求,就必须使用非阻塞的Socket连接和异步I/O。但使用异步I/O方式比使用同步I/O更难以控制,也更容易出错。因此,使用多线程和同步I/O可以更容易地处理类似于多请求的异步事件。
4. 使GUI更有效率
使用单线程来处理GUI事件时,必须使用循环来对随时可能发生的GUI事件进行扫描,在循环内部除了扫描GUI事件外,还得来执行其他的程序代码。如果这些代码太长,那么GUI事件就会被“冻结”,直到这些代码被执行完为止。
在现代的GUI框架(如SWING、AWT和SWT)中都使用了一个单独的事件分派线程(event dispatch thread,EDT)来对GUI事件进行扫描。当我们按下一个按钮时,按钮的单击事件函数会在这个事件分派线程中被调用。由于EDT的任务只是对GUI事件进行扫描,因此,这种方式对事件的反映是非常快的。
5. 节约成本
提高程序的执行效率一般有三种方法:
(1)增加计算机的CPU个数。
(2)为一个程序启动多个进程
(3)在程序中使用多进程。
第一种方法是最容易做到的,但同时也是最昂贵的。这种方法不需要修改程序,从理论上说,任何程序都可以使用这种方法来提高执行效率。第二种方法虽然不用购买新的硬件,但这种方式不容易共享数据,如果这个程序要完成的任务需要必须要共享数据的话,这种方式就不太方便,而且启动多个线程会消耗大量的系统资源。第三种方法恰好弥补了第一种方法的缺点,而又继承了它们的优点。也就是说,既不需要购买CPU,也不会因为启太多的线程而占用大量的系统资源(在默认情况下,一个线程所占的内存空间要远比一个进程所占的内存空间小得多),并且多线程可以模拟多块CPU的运行方式,因此,使用多线程是提高程序执行效率的最廉价的方式。
三、Java的线程模型
由于Java是纯面向对象语言,因此,Java的线程模型也是面向对象的。Java通过Thread类将线程所必须的功能都封装了起来。要想建立一个线程,必须要有一个线程执行函数,这个线程执行函数对应Thread类的run方法。Thread类还有一个start方法,这个方法负责建立线程,相当于调用Windows的建立线程函数CreateThread。当调用start方法后,如果线程建立成功,并自动调用Thread类的run方法。因此,任何继承Thread的Java类都可以通过Thread类的start方法来建立线程。如果想运行自己的线程执行函数,那就要覆盖Thread类的run方法。
在Java的线程模型中除了Thread类,还有一个标识某个Java类是否可作为线程类的接口Runnable,这个接口只有一个抽象方法run,也就是Java线程模型的线程执行函数。因此,一个线程类的唯一标准就是这个类是否实现了Runnable接口的run方法,也就是说,拥有线程执行函数的类就是线程类。
从上面可以看出,在Java中建立线程有两种方法,一种是继承Thread类,另一种是实现Runnable接口,并通过Thread和实现Runnable的类来建立线程,其实这两种方法从本质上说是一种方法,即都是通过Thread类来建立线程,并运行run方法的。但它们的大区别是通过继承Thread类来建立线程,虽然在实现起来更容易,但由于Java不支持多继承,因此,这个线程类如果继承了Thread,就不能再继承其他的类了,因此,Java线程模型提供了通过实现Runnable接口的方法来建立线程,这样线程类可以在必要的时候继承和业务有关的类,而不是Thread类。
转自 http://www.blogjava.net/nokiaguy/archive/2009/03/07/258358.html
相关推荐
### 线程简介 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有多个线程,这些线程共享进程的资源,如内存空间、文件句柄等,但它们拥有独立的执行路径和...
一、`Parallel`类简介 `Parallel`类提供了一系列静态方法,用于执行并行操作,如并行循环(`For`和`ForEach`)和并行查询(`Parallel LINQ (PLINQ)`)。这些方法内部会自动管理线程池,根据系统资源动态调整线程数量...
**Netty简介** Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。它提供了丰富的API,支持多种传输类型,如TCP、UDP和HTTP等,使得开发者能够方便地构建网络应用...
#### 一、Vert.x简介 Vert.x是一个强大的JVM框架,主要用于构建反应式(Reactive)应用。该框架能够帮助开发者实现异步、可伸缩且高性能的Web应用(当然不仅仅限于Web应用)。与Node.js相比,Vert.x更加灵活,因为...
#### Winsock 简介 Winsock 是 Windows 平台上的一组用于网络通信的 API 集合。它基于 BSD sockets 规范,并提供了对多种网络协议的支持,包括 TCP/IP 和 UDP。Winsock 的主要功能是创建、管理和关闭 socket 连接。...
项目简介 本项目是一个基于Java多线程的并发编程指南,旨在帮助开发者理解和掌握Java中的多线程编程技术。项目涵盖了多线程编程的核心概念、常见问题及其解决方案,包括线程的创建、启动、停止、生命周期管理、...
6. **链表转红黑树**:如果链表长度超过8,则转换为红黑树结构。 ##### 2.5 扩容机制 `ConcurrentHashMap`提供了两种触发扩容的方式: 1. 当链表长度达到8且数组长度小于64时,数组容量翻倍。 2. 当节点数量超过...
#### 一、OpenMP简介 **OpenMP**(开放式多线程)是一种用于共享内存系统的多线程并行编程模型,它通过简单的编译器指令来实现并行化,使得程序员可以更加专注于算法设计而减少对底层硬件细节的关注。OpenMP支持多种...
1. **线程简介** - 线程是程序执行的基本单元,每个线程都有自己的执行路径和独立的内存空间,即线程栈。 - 主线程是程序运行的入口点,每个进程至少有一个主线程。 - 进程和线程是操作系统中的关键概念,进程间...
#### Java Swing简介 - **Swing组件**:Swing是Java平台上的一个轻量级GUI工具包,它提供了丰富的UI组件,如按钮、文本框、列表、表格等。 - **容器**:在Swing中,`Container`是所有可以容纳其他组件的组件的基类。...
### 一、Select I/O 模型简介 Select模型是一种常用的I/O多路复用技术,在网络编程中被广泛应用于监听多个套接字的状态变化。该模型允许一个进程同时监控多个文件描述符(例如:套接字),并且可以在任一文件描述符...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程...第6章muduo 网络库简介125 6.1由来. ....
### Mina框架简介 Mina(Multipurpose Infrastructure Networked Applications)是Apache基金会下的一个开源项目,它是一个用于开发高性能和高扩展性网络应用程序的框架。Mina提供了抽象的、事件驱动的异步API,...
- **简介**:线程安全的后进先出(LIFO)堆栈,同样使用无锁算法,提供 `Push()` 添加元素到顶部,`Pop()` 移除并返回顶部元素,以及 `TryPop()` 方法。 5. **ConcurrentBag** - **特性**:无序元素集合,支持...
本资料主要涵盖了如何利用Android技术结合Afinal和Gson库来实现一个快速框架以及多线程下载功能。以下是相关知识点的详细介绍: 1. **Android快速框架**: - **Activity生命周期管理**:在Android应用开发中,理解...
- 参考《Windbg简介/启动Kernel Mode调试》指南启动Windbg。 2. **查看EPROCESS结构**: - 在Windbg的命令行输入`dt _EPROCESS`或`dt EPROCESS`。 - 这个命令会显示`_EPROCESS`结构的所有字段及其值。由于`...
项目简介 本项目是南京邮电大学Java课程的实验项目集合,涵盖了Java Swing图形界面设计、Applet小应用程序、流处理程序设计以及线程程序设计等多个实验内容。通过这些实验,学生能够深入理解和掌握Java在图形界面...
#### 二、数据通信技术简介 数据通信是指依据特定协议,在两个或多个终端之间传递数据的技术。它支持不同设备间的信息交互,包括计算机与计算机、计算机与终端以及终端与终端之间的数据传输。根据通信方式的不同,...