[Java之七]线程(1)
零:认知
回顾以前,【线程】这个概念我们其实很少听说过。
这就是学习的乐趣,当我们找不到一个更好的方法去解决一个问题的时候,我们就要去接触一个我们不知道的概念。来拓展我们的知识领域,来让我的们的行为更加有效。
到底是什么问题,让我们没有其他更好的方法去解决呢?
我们来看一下这个动图
||感谢Drake的动图
只有当其中一个小球执行完一个过程后,另一个小球才可以开始下落。是不是很不爽?
我们再来回想我们生活中的其他情况,我们手机程序,电脑程序,我们都可以同时来做很多事。可是在这里却不行。为什么?
一:线程
原因很简单,有的程序我们同时可以做很多事是因为,我们在这个程序里面开了很多的线程,我们的每个行为,都构成了一个线程的启动。
类比一下:
我们一般情况下,我们的的房子是我们要执行的程序,而我们的小河里面有我们的方法和属性。那我们要执行程序时,就像是我们要房子你要调用小河里面的水,我们的一个线程是指,调用这个水的顺序就,先给刚执行的A,当A执行完之后,才开始执行之后的B,C。也就是说单线程就是,我们只有当一个程序执行完之后我们才可以开始执行另一个。
那么什么是多线程呢?
再次类比:
当我想同时执行三个或者多个方法的时候,我们可以就像这条河一样,同时有三个支流。这样那一个程序我们都可以执行了。
二:方法实现
我们对于我们的代码我们要如何实现呢?
在Java中有很多可以实现的方法,而这次,我们先讲一种方法。继承Thraed的方法(也是一个最直接的方法)。以后慢慢补充。
既然Thread是可以继承的,也就是说Thread是一个类,我们先看看API怎么说(多从API里面找答案是一个好习惯):
为了实现多线程的方法,我们一般用Thread中run和start这两个方法就可以了。
具体的实现过程了是这样的:
我们继承Thread后,要重写run方法,将我们需要进行多线程的动作写到里面去,然后我们用start这个方法去调用。那么我就实现了多个线程。
出乎意料的简单?
三:举例
实现一个文件的查找:
我们如果去计算一个硬盘里面有多少文件,我们可以用一个程序去扫描,然后我们去计算,可是,如果我们一下子要去计算4个硬盘该怎么办呢?
用多线程就可以一次性4个硬盘同时计算,那么可以大大提高我们的效率。
我们先构建一个查询的方法:
public class J0725FindFile {
//Dir 的意思是目录
private String rootDirName;
//开始输出的是root地址(其中,这样的root地址就我们所说的硬盘)
//我们所用的方法就是一个构造方法
public J0725FindFile(String root){
this.rootDirName=root;
}
//我们开始要写一个方法,就是要将计算每个root里面的文件数量
public int countDir(String dir){
/**
* 我们如果要count出每个文件的数量,所以我们是自己不知道数量的多少的
* 那么我们要一直计算,直到我们无法计算为止
* 我们就用递归来计算,所以要加入判断条件
*/
int count = 0 ;
File dirfile =new File(dir);
if (!dirfile.exists()){
return count;
}
File [] subfile = dirfile.listFiles();
if(subfile==null){
return count;
}
//开始使用递归
//递归成为了让我们可以不断地去探寻文件,直到我们探寻不到了
for(int i = 0;i<subfile.length;i++){
if(subfile[i].isDirectory()){
count+=countDir(subfile[i].getAbsolutePath());
}
if(subfile[i].isFile()){
count++;
}
}
return count;
}
}
我们开始让其继承Thread然后重写run方法和调用start方法。
public void run(){
long start = System.currentTimeMillis();
int filecount= countDir(this.rootDirName);
long timeCost = System.currentTimeMillis()-start;
System.out.println(“—–驱动器:”+this.rootDirName+”统计完毕:”+” ;共有文件数量:”+filecount+” ;用时(单位:秒):”+timeCost/1000);
}
这个run方法调用了int filecount= countDir(this.rootDirName);方法,所以这个方法是可以有多个线程。
然后我们开始在我们主函数里调用start()。这个方法,来调用run();
import java.io.File;
public class J0725FindFile extends Thread{
//Dir 的意思是目录
private String rootDirName;
//开始输出的是root地址(其中,这样的root地址就我们所说的硬盘)
//我们所用的方法就是一个构造方法
public J0725FindFile(String root){
this.rootDirName=root;
}
//我们开始要写一个方法,就是要将计算每个root里面的文件数量
public int countDir(String dir){
/**
* 我们如果要count出每个文件的数量,所以我们是自己不知道数量的多少的
* 那么我们要一直计算,直到我们无法计算为止
* 我们就用递归来计算,所以要加入判断条件
*/
int count = 0 ;
File dirfile =new File(dir);
if (!dirfile.exists()){
return count;
}
File [] subfile = dirfile.listFiles();
if(subfile==null){
return count;
}
//开始使用递归
for(int i = 0;i<subfile.length;i++){
if(subfile[i].isDirectory()){
count+=countDir(subfile[i].getAbsolutePath());
}
if(subfile[i].isFile()){
count++;
}
}
return count;
}
/*
* 我们的计算任务写完了
* 如果我们需要用多线程来运行,从每个不同的盘里面开始,那么我们需要用写run方法
*/
public void run(){
long start = System.currentTimeMillis();
int filecount= countDir(this.rootDirName);
long timeCost = System.currentTimeMillis()-start;
System.out.println("-----驱动器:"+this.rootDirName+"统计完毕:"+" ;共有文件数量:"+filecount+" ;用时(单位:秒):"+timeCost/1000);
}
public static void main(String [] args ){
//构造方法的一些运用
File [] dirf = File.listRoots();
for(int i=0;i<dirf.length;i++){
J0725FindFile j =new J0725FindFile (dirf[i].getAbsolutePath());
j.start();△
}
System.out.println(dirf.length+"个线程已启动");
}
}
结果:
四.结尾
类比是伟大的学习方法
以上