热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

java多线程编程之java线程简介

线程是程序运行的基本执行单元,线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈

一、线程概述

线程是程序运行的基本执行单元。当操作系统(不包括单线程的操作系统,如微软早期的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类。


推荐阅读
  • 本文介绍如何通过SSH协议使用Xshell远程连接到Ubuntu系统。为了实现这一目标,需要确保Ubuntu系统已安装并配置好SSH服务器,并保证网络连通性。 ... [详细]
  • 本文将深入探讨PHP编程语言的基本概念,并解释PHP概念股的含义。通过详细解析,帮助读者理解PHP在Web开发和股票市场中的重要性。 ... [详细]
  • 微软Exchange服务器遭遇2022年版“千年虫”漏洞
    微软Exchange服务器在新年伊始遭遇了一个类似于‘千年虫’的日期处理漏洞,导致邮件传输受阻。该问题主要影响配置了FIP-FS恶意软件引擎的Exchange 2016和2019版本。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 优化局域网SSH连接延迟问题的解决方案
    本文介绍了解决局域网内SSH连接到服务器时出现长时间等待问题的方法。通过调整配置和优化网络设置,可以显著缩短SSH连接的时间。 ... [详细]
  • PHP中去除换行符的多种方法及应用场景
    本文将详细介绍在PHP中去除换行符的各种方法,并结合实际应用场景进行说明。通过本文,您将了解如何根据不同操作系统的特点,选择最合适的换行符处理方式。 ... [详细]
  • 深入解析 Spring Security 用户认证机制
    本文将详细介绍 Spring Security 中用户登录认证的核心流程,重点分析 AbstractAuthenticationProcessingFilter 和 AuthenticationManager 的工作原理。通过理解这些组件的实现,读者可以更好地掌握 Spring Security 的认证机制。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
  • 本文介绍如何处理服务器上使用curl命令访问HTTPS域名时出现的SSL连接错误问题。通过更新NSS库版本,可以有效解决这一常见问题。 ... [详细]
  • 在Python开发过程中,随着项目数量的增加,不同项目依赖于不同版本的库,容易引发依赖冲突。为了避免这些问题,并保持开发环境的整洁,可以使用Virtualenv和Virtualenvwrapper来创建和管理多个隔离的Python虚拟环境。 ... [详细]
  • PostgreSQL 10 离线安装指南
    本文详细介绍了如何在无法联网的服务器上进行 PostgreSQL 10 的离线安装,并涵盖了从下载安装包到配置远程访问的完整步骤。 ... [详细]
  • 本文探讨了在 ASP.NET MVC 5 中实现松耦合组件的方法。通过分离关注点,应用程序的各个组件可以更加独立且易于维护和测试。文中详细介绍了依赖项注入(DI)及其在实现松耦合中的作用。 ... [详细]
  • 如何配置DHCP服务器
    本文详细介绍了配置DHCP服务器的步骤,包括路由器设置和电脑端配置,确保设备能够自动获取IP地址并正常联网。 ... [详细]
  • 深入探讨智能布线管理系统的电子配线架应用
    本文详细介绍了电子配线架智能布线系统的核心优势,包括实时监测网络连接、提高操作准确性、图形化显示连接架构、自动识别网络拓扑、增强安全性等功能。该系统不仅提升了网络管理的效率和准确性,还为资产管理、报告生成以及与其他智能系统的集成提供了强大的支持。 ... [详细]
author-avatar
了不起的老狐_226
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有