java多线程编程(一基础概念)
1、进程和线程
进程,是一个正在运行的程序实体,windows下常见的就是xxx.exe,在任务管理器中可以看见很多个进程。它是线程的容器。
线程,是进程中的一个执行流。在单线程编程中,我们的程序只有一个执行流:主线程的main方法。流,表明执行的过程是有顺序的,如main函数中的语句需要一条一条的按顺序执行,第一条语句没执行完,就不能去执行第二条语句。
可见,单线程编程是有限制的,那就是我们的语句只能串行执行,不可能发生某些语句同时执行的现象。有时我们希望某些代码并行执行,就好比我们一边吃饭,一边看电视。这个时候,就需要使用多线程编程技术了。
需要注意的是:一个程序至少有一个线程,那就是主线程,它对应的方法是main方法。那么,其他线程的创建,就需要借助某一个先前已经存在的线程去创建和引发。这个先前存在的线程可以是主线程的main方法,也可以是被main创建的新的线程。
如下图,主线程中,运行到某个时刻,创建了(至于怎么创建新的线程稍后会讲解)新的线程thread-1,从此,CPU就比以前"忙"起来了,因为它要去执行2个线程总的代码。真的是“同时执行”2个线程的代码吗?答案是否定的。CPU本身是没有所谓的并行执行的能力的,也无所谓多线程,多线程是本机操作系统支持的。操作系统将进程线程进行管理,轮流(没有固定的顺序)分配每个进程很短的一段是时间(不一定是均分)。然后在每个线程内部,程序代码自己处理该进程内部线程的时间分配,多个线程之间相互的切换去执行,这个切换时间也是非常短的。因此多任务、多进程、多线程都是操作系统给人的一种宏观感受,从微观角度看,程序的运行是异步执行的。
我们知道就可以了,关于底层CPU到底如何做,我们并不需要关心。我们关心的是如何通过代码去创建和操作我们的线程。我们就当我们的线程都是“并行执行的”。
2、调用栈
什么是调用栈?在以前单线程编程中,就拿main函数来说吧。以一个列子来说明。
public class Test { public static int Add(int x,int y) { return x+y; } public static void main(String[] args) { int x =2,y = 5; int re = Add(x,y); System.out.println(re); } }
操作系统调用main函数,因为main函数是程序的入口,那么main函数就入栈了,main会占用一定的内存,因为里面有参数args和局部变量x,y,re。当执行到Add函数调用时,这时main函数“挂起”,执行流进入Add函数,Add函数入栈,同样系统也会为Add函数分配临时内存空间,当Add函数执行完,Add函数出栈,返回结果,它占用的内存被回收,执行流再次回到main函数,运行到println函数,println函数入栈。。。。。println出栈,执行流再回到main,main执行完毕,程序结束,系统回收本程序的内存。
注意:这里的栈只是一个操作系统管理函数调用的模型而已,并不是数据结构中的栈,只不够二者的逻辑结构是一致的:FILO。
在多线程编程中,每一个线程都有自己的一个调用栈,来管理自己的函数调用。
3、需要记住的事项
一、线程之间共享内存数据,这使得数据访问更加的快捷,方便。
二、一个使用多线程的程序,如果有任何一个线程没有结束,那么,这个程序就不会结束运行。
三、JVM的线程调度模式采用了抢占式模式。抢占式调度是根据线程的优先级别来获取CPU的使用权。但是这个也并不一定,CPU执行线程的顺序由操作系统和JVM共同
决定。但每一个线程的单次执行时间是一定的,这个时间叫时间片,在Linux系统中,默认时间片为1/100s。
作者:lulipro-代码钢琴家
出处:http://www.cnblogs.com/lulipro/
本文版权归作者和博客园共有,欢迎转载。限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。