注:本文章来IBM网站。
什么是线程?
几乎每种操作系统都支持进程的概念 ―― 进程就是在某种程度上相互隔离的、独立运行的程序。
线程化是允许多个活动共存于一个进程中的工具。大多数现代的操作系统都支持线程,而且线程的概念以各种形式已存在了好多年。Java 是第一个在语言本身中显式地包含线程的主流编程语言,它没有把线程化看作是底层操作系统的工具。
有时候,线程也称作轻量级进程。就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。它们共享内存、文件句柄和其它每个进程应有的状态。
进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。
Java 线程工具和 API 看似简单。但是,编写有效使用线程的复杂程序并不十分容易。因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰。
评论:线程是包含在进程之中,它们是并发的,独立的并有自己的局部变量和计数器。但是它们也共享内存,文件句柄,和其他进程。
你要做的就是,在一个线程处理在内存中处理数据时,不要被其他线程打搅。
每个 Java 程序都使用线程
每个 Java 程序都至少有一个线程 ― 主线程。当一个 Java 程序启动时,JVM 会创建主线程,并在该线程中调用程序的 main() 方法。
评论:main()将启动一个主线程。
为什么使用线程?
在 Java 程序中使用线程有许多原因。如果您使用 Swing、servlet、RMI 或 Enterprise JavaBeans(EJB)技术,您也许没有意识到您已经在使用线程了。
使用线程的一些原因是它们可以帮助:
使 UI 响应更快
利用多处理器系统
简化建模
执行异步或后台处理
评论:用不好的话,可就适得其返
响应更快的 UI 第 4 页
事件驱动的 UI 工具箱(如 AWT 和 Swing)有一个事件线程,它处理 UI 事件,如击键或鼠标点击。AWT 和 Swing 程序把事件侦听器与 UI 对象连接。当特定事件(如单击了某个按钮)发生时,这些侦听器会得到通知。事件侦听器是在 AWT 事件线程中调用的。
如果事件侦听器要执行持续很久的任务,如检查一个大文档中的拼写,事件线程将忙于运行拼写检查器,所以在完成事件侦听器之前,就不能处理额外的 UI 事件。这就会使程序看来似乎停滞了,让用户不知所措。
要避免使 UI 延迟响应,事件侦听器应该把较长的任务放到另一个线程中,这样 AWT 线程在任务的执行过程中就可以继续处理 UI 事件(包括取消正在执行的长时间运行任务的请求)。
利用多处理器系统
多处理器(MP)系统比过去更普及了。以前只能在大型数据中心和科学计算设施中才能找到它们。现在许多低端服务器系统 ― 甚至是一些台式机系统 ― 都有多个处理器。(现在都是双cpu了)
现代操作系统,包括 Linux、Solaris 和 Windows NT/2000,都可以利用多个处理器并调度线程在任何可用的处理器上执行。
调度的基本单位通常是线程;如果某个程序只有一个活动的线程,它一次只能在一个处理器上运行。如果某个程序有多个活动线程,那么可以同时调度多个线程。在精心设计的程序中,使用多个线程可以提高程序吞吐量和性能。
简化建模
在某些情况下,使用线程可以使程序编写和维护起来更简单。考虑一个仿真应用程序,您要在其中模拟多个实体之间的交互作用。给每个实体一个自己的线程可以使许多仿真和对应用程序的建模大大简化。
另一个适合使用单独线程来简化程序的示例是在一个应用程序有多个独立的事件驱动的组件的时候。例如,一个应用程序可能有这样一个组件,该组件在某个事件之后用秒数倒计时,并更新屏幕显示。与其让一个主循环定期检查时间并更新显示,不如让一个线程什么也不做,一直休眠,直到某一段时间后,更新屏幕上的计数器,这样更简单,而且不容易出错。这样,主线程就根本无需担心计时器
异步或后台处理
服务器应用程序从远程来源(如套接字)获取输入。当读取套接字时,如果当前没有可用数据,那么对 SocketInputStream.read() 的调用将会阻塞,直到有可用数据为止。
如果单线程程序要读取套接字,而套接字另一端的实体并未发送任何数据,那么该程序只会永远等待,而不执行其它处理。相反,程序可以轮询套接字,查看是否有可用数据,但通常不会使用这种做法,因为会影响性能。
但是,如果您创建了一个线程来读取套接字,那么当这个线程等待套接字中的输入时,主线程就可以执行其它任务。您甚至可以创建多个线程,这样就可以同时读取多个套接字。这样,当有可用数据时,您会迅速得到通知(因为正在等待的线程被唤醒),而不必经常轮询以检查是否有可用数据。
使用线程等待套接字的代码也比轮询更简单、更不易出错。
简单,但有时有风险
虽然 Java 线程工具非常易于使用,但当您创建多线程程序时,应该尽量避免一些风险。
当多个线程访问同一数据项(如静态字段、可全局访问对象的实例字段或共享集合)时,需要确保它们协调了对数据的访问,这样它们都可以看到数据的一致视图,而且相互不会干扰另一方的更改。为了实现这个目的,Java 语言提供了两个关键字:synchronized 和 volatile。我们将稍后在本教程中研究这些关键字的用途和意义。
当从多个线程中访问变量时,必须确保对该访问正确地进行了同步。对于简单变量,将变量声明成 volatile 也许就足够了,但在大多数情况下,需要使用同步。
如果您将要使用同步来保护对共享变量的访问,那么必须确保在程序中所有访问该变量的地方都使用同步。
不要做过头
虽然线程可以大大简化许多类型的应用程序,过度使用线程可能会危及程序的性能及其可维护性。线程消耗了资源。因此,在不降低性能的情况下,可以创建的线程的数量是有限制的。
尤其在单处理器系统中,使用多个线程不会使主要消耗 CPU 资源的程序运行得更快。
评论:这句话说的对”物极必反“,”适合自己的才是最好的“
示例:使用一个线程用于计时,并使用另一个线程完成工作
以下示例使用两个线程,一个用于计时,一个用于执行实际工作。主线程使用非常简单的算法计算素数。
在它启动之前,它创建并启动一个计时器线程,这个线程会休眠十秒钟,然后设置一个主线程要检查的标志。十秒钟之后,主线程将停止。请注意,共享标志被声明成 volatile。
/**
* CalculatePrimes -- calculate as many primes as we can in ten seconds
*/
public class CalculatePrimes extends Thread {
public static final int MAX_PRIMES = 1000000;
public static final int TEN_SECONDS = 10000;
public volatile boolean finished = false;
public void run() {
int[] primes = new int[MAX_PRIMES];
int count = 0;
for (int i=2; count<MAX_PRIMES; i++) {
// Check to see if the timer has expired
if (finished) {
break;
}
boolean prime = true;
for (int j=0; j<count; j++) {
if (i % primes[j] == 0) {
prime = false;
break;
}
}
if (prime) {
primes[count++] = i;
System.out.println("Found prime: " + i);
}
}
}
public static void main(String[] args) {
CalculatePrimes calculator = new CalculatePrimes();
calculator.start();
try {
Thread.sleep(TEN_SECONDS);
}
catch (InterruptedException e) {
// fall through
}
calculator.finished = true;
}
}
小结
Java 语言包含了内置在语言中的功能强大的线程工具。您可以将线程工具用于:
增加 GUI 应用程序的响应速度
利用多处理器系统
当程序有多个独立实体时,简化程序逻辑
在不阻塞整个程序的情况下,执行阻塞 I/O
当使用多个线程时,必须谨慎,遵循在线程之间共享数据的规则,我们将在共享对数据的访问中讨论这些规则。所有这些规则归结为一条基本原则:
不要忘了同步。
分享到:
相关推荐
Java线程基础教程完整版
java 线程基础入门 一个关于计算机的简化的视图是:它有一个执行计算的处理机、包含处理机所执行的程序的ROM(只读存储器)、包含程序所要操作的数据的RAM(只读存储器)。在这个简化视图中,只能执行一个作业。一个...
IBM JAVA java 多线程 教程 线程简介 从IBM弄到的java线程基础教程
java 线程实例 java线程基础练习 线程实例代码
本教程研究了线程的基础知识 — 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单程序。
本教程研究了线程的基础知识 — 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用程序的基本构件 — 如何在线程之间交换数据、如何控制 线程以及线程如何...
java多线程基础(英文),本文包括线程基础,生命周期,数据访问,线程同步等内容.
这套课程既可以作为从零基础开始...课程的主要内容涉及有JAVA基础课程、JAVA多线程与并发编程、数据库开发基础和进阶、Spring Framework、Spring进阶、Spring MVC框架、Spring boot、Java常用类库、Java异常处理等等
java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...
Java线程基础信息 java线程操作机制 java线程运行机制 通过芯片的速度越来越快,散热也越来越困难。很久都没有看到CPU的原始速度有重大提升了。但我们仍然看到摩尔定律在起作用,CPU的设计者们继续在向每片硅晶上...
Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...
JAVA多线程基础DEMO,都是一些基础演练,希望可以帮到你
java多线程基础资料,java多线程基础资料
主要介绍了java线程的基础实例解析,具有一定借鉴价值,需要的朋友可以参考下
Java线程 java 线程介绍说明 适用于有一定基础的
java多线程基础说课PPT教案.pptx
不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。...JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要清楚在jvm内存模型的基础上,如果解决多线程的可见性和有序性。
操作系统,网络协议,Java基础,Java线程,java并发,mysql,redis,分布式讲解,基础算法