Java之多线程与方法调用

时间:2021-07-19 18:35:58

  一种是通过实现Runnable接口,另一种是在主方法实现。

一、第一种 实现javalangRunnable接口

循环输出0-99100个数字。

public class TestThread1{

publicstatic void main(String args[]){

Runner1r = new Runner1(); //new一个线程对象Runner1

//r.start();//通知CPU要启动线程

//r.run();//方法调用



Thread t = new Thread(r); //为了启动Runner1这个线程,需要实例化Thread,并传入自己的Runner1实例

t.start();//通知CPU要启动线程



for(inti = 0; i<100; i++){

System.out.println("MainThread:-----" + i);

}

}

}



class Runner1 implements Runnable{ //实现Runnable接口

//class Runner1 extends Thread{ //本身就是一个Thread,就不用再new一个

publicvoid run(){ //run方法里写的是什么,线程调用时执行的就是什么

for(inti=0; i<100; i++){ //从0-99挨个输出

System.out.println("Runner1:" + i);

}

}

}

运行结果:

                        Java之多线程与方法调用

运行顺序图:

                  Java之多线程与方法调用

   Runner1类通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个约定。所有的多线程代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。

   在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target)构造出对象,然后调用Thread对象的start()方法来运行多线程代码。

二、第二种 扩展javalangThread

public class TestThread1{

publicstatic void main(String args[]){

Runner1r = new Runner1(); //new一个线程对象Runner1

r.start();//通知CPU要启动线程

//r.run();//方法调用



//Threadt = new Thread(r);

//t.start();



for(inti = 0; i<100; i++){

System.out.println("MainThread:-----" + i);

}

}

}



//class Runner1 implements Runnable{ //实现Runnable接口

class Runner1 extends Thread{ //本身就是一个Thread,就不用再new一个

publicvoid run(){ //run方法里写的是什么,线程调用时执行的就是什么

for(inti=0; i<100; i++){ //从0-99挨个输出

System.out.println("Runner1:" + i);

}

}

}

运行结果:

                         Java之多线程与方法调用

   程序启动运行main时候,java虚拟机启动一个进程,主线程mainmain()方法调用时候被创建。随着调用r的对象的start方法,另外的一个线程也启动了,这样,整个应用就在多线程下运行。

实际上所有的多线程代码都是通过运行Threadstart()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的。

使用继承会比较死,从这个类继承之后就不能再从其他的类去继承,但是如果如果用的是接口,若实现了这个接口之后,还可以从其他的类继承,还可以实现其他的接口。所以,从接口来说实现接口会比较灵活,原则是能使用接口的时候不要从Thread类继承。总之,如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易实现资源共享。

PSstart()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。从程序运行的结果可以发现,多线程程序是乱序执行,所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。因此,只有乱序执行的代码才有必要设计为多线程。

三、方法调用

按调用的顺序执行,为了方便查看,循环输出改为0-910个数。

public class TestThread1{

publicstatic void main(String args[]){

Runner1r = new Runner1(); //new一个线程对象Runner1

//r.start();//通知CPU要启动线程

r.run();//方法调用



//Threadt = new Thread(r);

//t.start();



for(inti = 0; i<10; i++){

System.out.println("MainThread:-----" + i);

}

}

}

//class Runner1 implements Runnable{ //实现Runnable接口

class Runner1 extends Thread{ //本身就是一个Thread,就不用再new一个

publicvoid run(){ //run方法里写的是什么,线程调用时执行的就是什么

for(inti=0; i<10; i++){ //从0-9挨个输出

System.out.println("Runner1:" + i);

}

}

}

运行结果:

                   Java之多线程与方法调用

运行顺序图:

 Java之多线程与方法调用

   按调用方法的顺序执行,先子线程执行完了,主线程才开始执行。

输出的时候根据main方法里调用的顺序,会先执行r.run()方法里的循环体,打印输出为"Runner1" + i,当执行到main方法里的循环体的时候再次打印输出,输出为"MainThread:-----" + i

四、线程与进程的区别

简单理解线程与进程:

线程指的是程序里不同的执行路径,看上述的运行顺序图,机器上实际上运行的是线程;

进程是一个静态的概念,一个进程里有一个主线程叫做main()方法,是一个程序、一个进程里面的不同的执行路径。

区别:

   1.每个进程都有独立的代码和数据空间,进程的切换会有较大的开销

   2.线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程的切换开销小。