每个java都至少有一个线程---主程序当一个java程序启动时。JVM会创建主线程,并在线程中调用主程序的main()方法。
线程可以理解为“程序内部一个独立运行单位”。
在接触线程之前我们学过的都是单线程。
单线程,程序运行时的调用模式是:顺序调用。
如下
public void a(){
b();
c();
}
public void b(){
d();
}
public void d(){}
public void c(){}
只有当一个方法执行完下一个方法才能被执行,这个就是单线程的特点。
而多线程模型是将代码方法一个独立的运行单元中即线程中,让多个调用并行被执行。
2.线程和进程的区别
(1)简单来说一个进程就是一个应用程序,而线程是一个进程中多个独立运行单位。
(2)多个进程的内部数据和状态是完全独立的,而一个进程中的多个线程是共享一块内存空间和一组系统资源的,在程序内部可以互相调用,而进程间的通信大多都要通过网络实现。如我们访问google,就是我们自己机器上的IE进程和google的web服务器进程之间的通信。
(3)线程本身的数据一般寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要
小。
3.实现多线程的三个常用方法
(1)继承Thread类
(2)实现Runable接口
(3)以匿名内部内的方式创建线程
下面以统计某磁盘文件总数为例子介绍线程。
创建统计文件的线程类
/** * 计算某个目录下文件的个数类 * 该类继承Thread线程类 * */ public class CountFile extends Thread{ private String path;//声明目录路径属性 /** * 定义构造方法 * @param path要统计的目录路径 */ public CountFile(String path){ this.path=path; } /** * 定义统计文件个数的方法 * @param path要统计的目录路径 * @return返回文件个数 */ private int count(String path){ //声明计数变量 int count=0; File file=new File(path); //判断该文件是否存在 if(file.exists()){ //如果存在的话,再判断是目录还是文件,是目录的话,获取该目录下文件,然后递归 if(file.isDirectory()){ File [] files=file.listFiles(); //判断files是否为空 if(files==null){ return count; }else{ //遍历该目录下的文件 for(int i=0;i<files.length;i++){ count+=count(files[i].getAbsolutePath()); } } }else if(file.isFile()){ //如果是文件count累加1 count++; } }else{ return count; } return count; } /** * 重写父类中run()方法 */ public void run(){ //定义开始计数的时间 long startime=System.currentTimeMillis(); //调用统计的方法 int count=count(path); //定义结束计数时的时间 long endtime=System.currentTimeMillis(); System.out.println("磁盘"+path+"共有文件"+count+"个,用时"+(endtime-startime)/1000+"s"); } }
在主函数中实例化该线程对象并启动线程
/** * 线程测试类 * * */ public class ThreadTest { /** * 主函数 */ public static void main(String[] args) { //获取系统根目录 File [] files=File.listRoots(); //遍历数组,统计各个根目录下的文件总数 for(int i=0;i<files.length;i++){ //实例化线程对象 CountFile cf=new CountFile(files[i].getAbsolutePath()); //启动线程 cf.start(); } System.out.println(files.length+"个线程已经启动"); } }
运行结果如下
5个线程已经启动
磁盘G:\共有文件0个,用时0s
磁盘F:\共有文件2397个,用时0s
磁盘E:\共有文件4789个,用时0s
磁盘D:\共有文件14042个,用时1s
磁盘C:\共有文件86228个,用时18s
我们可以看出输出语句“5个线程已经启动”是放在最后面的但他最先输出,其实主函数也是一个线程,线程并不是同时运行,而是隔着非常短的时间间隔,一个运行一会在隔一段时间另一个运行,这个时间间隔是非常短的,我们是无法感觉到这个时间间隔的,所以在这写输出语句中哪一个先运行完就那个先输出。所以也就出现了以上的结果。
上面介绍了继承Thread类来实现多线程,另外的还可以实现Runnable接口来实现,其他都一样。
还有一个就是一匿名内部类的形式创建。
如下:
public void Mythread_count(final String path){ Thread thread=new Thread(){ public void run() { System.out.println("++++++++++"); //调用统计文件个数的方法 int count=count(path); System.out.println("磁盘"+path+"共有"+count+"个"+"文件"); }}; //启动线程 thread.start(); }
这样也能实现多线程。