Java多线程初学者指南(1):线程简介[Java编程]
本文“Java多线程初学者指南(1):线程简介[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
1、线程概述
线程是程序运行的基本履行单元.当操作系统(不包含单线程的操作系统,如微软早期的DOS)在履行一个程序时,会在系统中成立一个进程,而在这个进程中,必须至少成立一个线程(这个线程被称为主线程)来作为这个程序运行的进口点.因此,在操作系统中运行的任何程序都至少有一个主线程.
进程和线程是现代操作系统中两个必不可少的运行模子.在操作系统中可以有多个进程,这些进程包含系统进程(由操作系统内部成立的进程)和用户进程(由用户程序成立的进程);一个进程中可以有一个或多个线程.进程和进程之间不同享内存,也就是说系统中的进程是在各自独立的内存空间中运行的.而一个进程中的线可以同享系统分配给这个进程的内存空间.
线程不但可以同享进程的内存,并且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈, 是在成立线程时由系统分配的,主要用来保存线程内部所利用的数据,如线程履行函数中所定义的变量.
注意:任何一个线程在成立时城市履行一个函数,这个函数叫做线程履行函数.也可以将这个函数看做线程的进口点(近似于程序中的main函数).无论利用什么语言或技术来成立线程,都必须履行这个函数(这个函数的表现情势大概不一样,但城市有一个这样的函数).如在Windows顶用于成立线程的API函数CreateThread的第三个参数就是这个履行函数的指针.
在操作系统将进程分成多个线程后,这些线程可以在操作系统的管理下并发履行,从而大大提高了程序的运行效率.固然线程的履行从宏观上看是多个线程同时履行,但实际上这只是操作系统的障眼法.由于一块CPU同时只能履行一条指令,因此,在拥有一块CPU的计算机上不大概同时履行两个任务.而操作系统为了能提高程序的运行效率,在一个线程闲暇时会撤下这个线程,并且会让其他的线程来履行,这种方法叫做线程调度.我们之所以从表面上看是多个线程同时履行,是因为差别线程之间切换的时间非常短,并且在普通情形下切换非常频繁.假定我们有线程A和B.在运行时,大概是A履行了1毫秒后,切换到B后,B又履行了1毫秒,然后又切换到了A,A又履行1毫秒.由于1毫秒的时间关于常人来说是很难感知的,因此,从表面看上去就象A和B同时履行一样,但实际上A和B是交替履行的.
2、线程给我们带来的好处
假如能公道地利用线程,将会削减开辟和保护本钱,乃至可以改进复杂利用程序的性能.如在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的运行方法,因此,利用多线程是提高程序履行效率的最便宜的方法.
3、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类.
以上是“Java多线程初学者指南(1):线程简介[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |