??首先要了解什么是进程(Process),什么是线程(Thread)。
??进程,即进行中的程序。比如qq之类的,当它运行起来之后计算机会为它分配系统资源,这就是一个进程。一个进程中可以包含若干个(至少一个)线程,比如qq中可能同时要提供多个聊天窗口的实时更新,就需要有多个线程共同运作。线程的运行由cpu安排调度(单核cpu也能模拟出多线程效果,即在多个线程之间快速切换,造成一种在同时进行的假象。不过真实的多线程还是要靠多个cpu实现)。
??我们在写java代码的时候,main函数就是一个线程入口,一般叫它主线程。
知道了基本概念之后,我们可以试着来写一个demo,有三个基本步骤:
??1.继承Thread类
??2.重写run方法
??3.执行start方法
public class LearnThread extends Thread{
@Override
public void run() {
for(int i=0;i<500;++i){
System.out.println(i+"--多线程启动--");
}
}
public static void main(String[] args) {
LearnThread t1=new LearnThread();
t1.start();
for(int i=0;i<500;++i){
System.out.println(i+"--Main启动--");
}
}
}
??这样就是一个简单的demo,由于计算机运行速度不同,你可能在你的电脑上运行这段代码看不到多线程效果。但是没关系,你可以试着把两个for循环中i的上限值变大,或者看看我的运行结果(的一部分)。
415--多线程启动--
416--多线程启动--
417--多线程启动--
418--多线程启动--
488--Main启动--
419--多线程启动--
489--Main启动--
490--Main启动--
491--Main启动--
492--Main启动--
??显然,我的计算机是单核的,它在执行这个多线程程序中使用的策略正是交替执行各个线程,来造成多线程共同执行的假象。但是你仍然可以在这样的结果中得到有用的信息。我们在运行main函数时,系统开启了一个线程(主线程),它创造了一个LearnThread类,并且调用了这个类的start方法(start方法的作用是告诉CPU,这里有一个可以被执行的线程,至于什么时候执行它由CPU来安排。如果在这里我们不调用start方法,而是直接调用重写过的run方法,那么很不幸,CPU不会把它看成另一个可以被执行的线程,而只会认为这是主线程中的一个普通的函数调用,然后它会先循环输出五百次的“多线程启动”,接着输出五百次的“Main启动”)。此时,CPU知道现在有两个线程可以被执行,它会按照自己的策略去交替执行这两个线程,这也就是上面展示的交替输出的原因。如果你的CPU运行速度足够快,它可能还没来得及交替执行另一个线程,当下在运行的线程任务就已经结束了,这就是我让你把i的上限提高的原因。
??最后,让我们用一个简单的例子来结束这一小节。你可以仿造这个样例来写一个你自己的多线程样例来加深理解。
class threadTest extends Thread{
String name;
threadTest(String name){
this.name=name;
}
@Override
public void run() {
for(int i=0;i<500;++i){
}
System.out.println(name+" finished!");
}
}
public class LearnThread {
public static void main(String[] args) {
threadTest t1=new threadTest("线程1");
threadTest t2=new threadTest("线程2");
threadTest t3=new threadTest("线程3");
t1.start();
t2.start();
t3.start();
}
}
??下面是我的运行结果,看起来它并不和我调用start方法的顺序一致,但是你现在应该知道为什么会这样了。
线程1 finished!
线程3 finished!
线程2 finished!
|