多线程
我个人认为这是个难点,因为牵涉到多线程我就完全要被代码控制了,总感觉它的执行根本就不是我的意愿。不过,还是简单的小结一下吧。
首先,从名称上,我们要区分:进程和线程。之前我也是完全分不清这两个有什么区别。现在才有了一点点了解。不过我还是不懂线程。一般来说,我们运行一个应用程序的时候,就启动了一个进程,当然有的还会启动多个进程。我们打开任务管理器可以看到电脑正在进行的应用程序和进程有哪些。启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的。而一个进程可以包含多个线程,线程之间可以进行数据交换,实时通信和必要的同步操作。但是进程间是独立的。他们之间不存在数据共享的问题。
讲到计算机中数据的交换,就还有一个要了解的就是并行和串行的问题。串行是计算机与I/O设备之间仅通过一条传输线交换数据,数据的各位是按顺序一次一位一位进行传送的。并行是指计算机与I/O设备之间仅通过一条传输线交换数据,数据的各位是同时进行传送的。通常并行的通信速度要快得多。任何一个Java程序都至少有一个线程,即为主线程(main thread )。当JVM加载代码时,发现main方法后就会启动一个线程(main线程)。我们还可以在main方法的执行过程中创建其他的线程来共同完成某项任务。多线程编程可以提高代码运行效率。
通常我们所说的多线程也是CPU不断切换操作内容,只是它是以毫秒计时的高速运行速度来切换执行不同的线程的,我们根本就察觉不出来罢了。假如我们需要执行多个任务,如果只使用一个线程,那么这些任务需要一个接一个的去执行,完成。即使在执行某个任务的时候,可能也要产生等待状态,此时cpu不处理有关的数据处理。而如果使用两个线程,则整个运行的效率会提高很多,因为在某个任务等待的时候,另外的线程也可使用CPU,这样效率就明显高于单线程了。
下面是利用多线程来统计系统盘中的文件个数:
package threadTest1;
import java.io.File;
public class MainFile {
/**
* @param args
*/
public static void main(String[] args) {
File[] rootdirs = File.listRoots();
for(int i=0;i<rootdirs.length;i++){
String path=rootdirs[i].getAbsolutePath();
System.out.println(path+"线程已经启动!");
FileThread fd=new FileThread(path);
fd.start();
}
}
}
package threadTest1;
import java.io.File;
public class FileThread extends Thread{
String path;
File file;
//当创建线程对象时,传入一个地址参数
public FileThread(String path){
this.path=path;
file= new File(path);
}
public void run(){
count(file);
}
/**
* 统计指定的文件中的文件个数
* @param file 需要统计的文件夹
* @return 返回统计的结果
*/
public int count(File file){
int counts=0; //定义一个统计文件的计数器
if(!file.exists()){ //判断文件是否是真实存在
System.out.println("文件不存在!");
return 0;
}
if(file.isDirectory()){ //判断文件是否是目录
//System.out.println("这是一个文件目录:"+file.getAbsolutePath());
File[] subfile=file.listFiles(); //返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
if(null==subfile||subfile.length==0){ //判断数组中的文件是否是目录
return 0;
}
for(int i=0;i<subfile.length;i++){ //遍历当前文件
if(subfile[i].isDirectory()){ //判断当前目录中的文件是否是子目录
String subdir=subfile[i].getAbsolutePath();//返回此抽象路径名的绝对路径名字符串。
//System.out.println("目录:"+subdir);
File fe=new File(subdir);
counts+=count(fe); //递归调用,并且累计文件的个数
}
if(subfile[i].isFile()){ //判断文件是否是标准文件
counts++;
String fileName=subfile[i].getAbsolutePath();//返回此抽象路径名的绝对路径名字符串。
//System.out.println("文件"+counts+"是:"+fileName);
}
}
}
try{
Thread.sleep(1000);
}catch(Exception e){
e.getStackTrace();
}
System.out.println(file+"中总共有:"+counts+"个文件");
return counts;
}
}
还有一个需要知道的就是线程的各种状态:
(1).新建
当一个Thread 类或其子类的对象被声明并创建对象时,新生的线程对象处于新建状态。此时他也已经有了相应的内存空间和其他资源。
(2).运行
创建了一个线程后,它还仅仅是占了内存资源,但在JVM管理的线程中并没有这个线程。所以还需要调用start(),这样就可以通知JVM又有一个新线程在排队等候切换了。当改线程拥有了CPU的使用权时,就会执行它的run()方法。父类Thread中的run()没有具体的方法,子类中需重写。
(3).中断
A.中断的原因有多种,可能执行了sleep(int millsecond)方法
B.JVM将CPU资源从当前线程切换给其他线程了。
C.执行了wait()方法
(4).死亡
现在还真不懂得线程,还得慢慢学习!