创建多线程的两种方式

API中告诉我们创建线程有2种方式:
第一种:
1、定义一个类继承Thread
2、子类复写Thread类中的run方法
3、创建子类对象(子类就是一个线程类)

4、启动子类对象

/*
 * 演示创建线程的第一种方式
 */
//定义子类,继承Thread
class Demo extends Thread{
	
	//复写run方法
	public void run(){
		
		for( int i=0;i<20;i++ ){
			System.out.println("demo run i = "+i);
		}
	}
}

public class ThreadDemo {
	public static void main(String[] args) {
		
		//创建子类对象
		Demo d = new Demo();
		//启动线程
		d.start();

		for( int i=0;i<20;i++ ){
			System.out.println("main i = "+i);
		}
		
	}
}
分析:
1)、为什么要继承Thread类?
线程是计算机中程序运行的一个独立单元,这个单元Java使用Thread类进行了描述。现在我们需要自己使用线程,执行我们自己的某些代码。
Thread类是Java中提供的原生的类,而我们具体需要操作线程时,不能直接去使用Thread,如果直接去使用的Thread,导致原生的Thread类无法知道我们后期真正需要让线程执行的代码。
API中告诉我们需要自己定义一个类继承Thread,我们自己的类继承了Thread那么自己的类就变成线程类,就继承到Thread类中的所有功能,我们自己的类就可以去使用Thread类中定义的所有操作线程的功能。

继承Thread类的目的就是让自己的类变成线程类。可以去操作线程。
2)、线程是计算机中程序运行的一个独立单元,这个单元Java使用Thread类进行了描述。现在我们需要自己使用线程,执行我们自己的某些代码。
Thread类是Java中提供的原生的类,而我们具体需要操作线程时,不能直接去使用Thread,如果直接去使用的Thread,导致原生的Thread类无法知道我们后期真正需要让线程执行的代码。
API中告诉我们需要自己定义一个类继承Thread,我们自己的类继承了Thread那么自己的类就变成线程类,就继承到Thread类中的所有功能,我们自己的类就可以去使用Thread类中定义的所有操作线程的功能。

继承Thread类的目的就是让自己的类变成线程类。可以去操作线程。
2)、为什么要复写run方法
我们开启线程的目的是让多部分代码同时运行,让线程去执行我们自己的某些代码,而这些代码需要交给线程运行,那么我们就必须按照线程运行时会调用的某些固定的功能。
当我们调用start方法的时候,JVM在底层会自动的调用run方法,而run方法中的代码就会被某个线程去执行。
而我们开启线程的目的就是希望线程执行某些代码,也就是只要大家把需要线程执行的代码书写在run方法中,一旦开启线程,run方法会自动的运行  过,那么就会 导致 书写在run方法中的所有代码会被当前某个线程去调用执行。
复写run方法的目的:就是希望在run方法中书写线程要执行的那么代码。
线程要执行的代码:称为线程的任务。
3)为什么不直接调用run方法,而调用start方法
如果我们直接调用run方法,这时虽然有线程对象,但是并没有让线程真正开启,而不开启线程,直接通过线程对象调用run方法,这个和我们以前学习的对象调用普通方法没有任何区别,这些调用的功能都会在主线程所在的区域中运行。

如果我们有了线程对象,希望线程可以独立去运行,只能手动调用Thread类提供的start方法,才能在栈内存中开启一个新的执行通道(路径),这样才能保证run方法会被加载到新的执行路径中去运行。

开启线程的第二种方式

1、定义一个类 实现 Runnable 接口
2、实现接口中的run方法
3、创建实现类的对象
4、创建Thread对象,把实现类对象作为参数传递
5、Thread对象开启线程

/*
 * 演示创建线程的第二种方式
 */
class Demo2 implements Runnable{
	
	//实现run方法
	public void run() {
		for( int i=0;i<20;i++ ){
			System.out.println("demo2 run i = "+i);
		}
	}
}
public class ThreadDemo2 {
	public static void main(String[] args) {
		
		//创建实现类的对象
		Demo2 d  = new Demo2();
		
		//创建Thread对象
		Thread t = new  Thread( d );
		
		//开启线程
		t.start();
		
		for( int i=0;i<20;i++ ){
			System.out.println("main i = "+i);
		}
	}
}<span style="color:#ff0000;">
</span>
分析:实现Runnable的原理:
1)、Java中继承的局限性
Java只支持单继承,不支持多继承。如果一个类已经有父类了,但这个类中有部分代码需要多线程操作,这时我们就没有办法再让这个类去继承Thread。也就是Java中提供的第一种方式就无法使用。导致没有办法去操作多线程了。

Thread类是描述线程,Thread类就应该只定义如何去操作线程的功能,在Thread中提供了一个run方法,而这个run方法是专门用来明确线程要执行的任务的方法。于是就run方法从Thread类中抽离出来,专门定义了一个接口,后期真正在开发中,如果要明确线程的任务,找对应的接口,如果要操作线程就直接找Thread。
2)、Java中提供的接口的作用
           1、 给事物体现添加(增加)扩展功能。
           2、给事物双方定义规则。
Runnable接口它其实是在定义线程中操作任务的一个规则。线程是可以操作任务的,而任务是需要后来程序书写和明确的。只有我们明确的任务符合Runnable接口的规范,那么Thread才能去真正调用run方法。
3)、其他的技术问题:
1、我们在创建Thread类的时候,其实只是明确了线程对象
2、书写的实现了Runnable接口的类,相当于明确了线程要执行的任务类,当我们创建了实现类对象,就相当于明确了线程要执行的任务对象。
3、需要在创建Thread对象的时候,把线程的任务对象传递给Thread,这样就让线程对象和任务对象之间产生了关系。
4、我们调用Thread的start方法的时候,就会根据对应的关系调用到其中的run方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值