现在我们有这么一个需求,就是在主线程在运行的同时,我们想做其他的任务,这个时候我们就用到了多线程。那么如何创建多线程,我们知道在系统当中qq的多线程创建是由操作系统来完成的,那么如果我们想在java当中创建多线程的话,应该如何去做呢?解决问题的时候,我们第一个应该想到的是,java当中是否给我们提供了解决该问题的对象,并且把这个对象暴漏出来供我们使用,特别是设计系统。这个时候我们去查阅javaapi。
创建线程的步骤:
1、创建一个类继承Thread类,此时这个类也就是线程
2、在该类当中覆盖Thread类的run()方法。
3、直接创建Thread子类的对象创建线程。
4、调用start()方法,开启线程,并且调用线程任务的run()方法。
在javaapi当中有一个Thread类,如果我们要使用创建多线程的话,我们应该继承Thread类,同时覆盖Thread类当中的run方法。那么为什么要覆盖Thread类当中的run方法呢?因为在Thread类本身也可以创建对象,这个对象也是有run方法的。那么我们创建线程的目的,就是去开启一个新的新的执行路径,去运行指定的代码,和其他代码一起运行。而运行的指定代码就是这个执行路径的任务。
JVM创建的主线程的任务都定义在主函数当中,而自定义的线程的任务定义在什么地方呢?Thread用于描述线程,线程是需要任务的,Thread类也有对任务的描述,这个任务就是通过Thread类当中的run()方法,那么就是run()方法就是用来封装自定义线程任务的函数。Thread描述线程->线程有任务才有意义->run()方法封装任务代码
run方法当中就是定义的线程要运行的任务代码。
如果我们要直接使用Thread当中的run()方法,那么就没有意义了,因为在run方法当中的不是我们想要执行的代码。
开启线程是为了执行指定代码,所以只有继承了Thread类,并且将要执行的指定代码封装到run方法当中,这样就可以。
代码示例:
1 /**
2 *创建线程的方法一:
3 *1、定义一个类继承自Thread类
4 *2、在该子类当中覆盖Thread类当中的run()方法,把要执行的指定代码封装到run()方法当中
5 *3、创建该子类的对象
6 *4、调用对象的start()方法,开启线程,并且调用线程当中run()方法
7 */
8 class Demo5 extends Thread//1---定义一个类继承自Thread类
9 {
10 private String name;
11
12 Demo5(String name)
13 {
14
15 this.name = name;
16
17 }
18 //2----在该子类当中覆盖Thread类当中的run()方法,把要执行的指定代码封装到run()方法当中
19 public void run()
20 {
21
22 for(int x = 0; x<=10 ; x++)
23 {
24
25 System.out.println("x ... is "+x);
26
27 }
28
29 }
30
31 }
32
33 class ThreadDemo5
34 {
35
36 public static void main(String[] args) {
37
38 Demo5 d1 = new Demo5("Mike");//3---创建该子类的对象
39 Demo5 d2 = new Demo5("Lili");//3---创建该子类的对象
40 d1.start();//4-----调用对象的start()方法,开启线程,并且调用线程当中run()方法
41 d2.start();//4-----调用对象的start()方法,开启线程,并且调用线程当中run()方法
42 }
43
44 }
如果我们开启了多线程,我们如何区分这些线程呢,我们查阅java api可以知道,可以通过getName()可以获得线程的名称。
1 class Demo2 extends Thread
2 {
3
4 public void run()
5 {
6
7 for(int i = 0; i<=10 ; i++)
8 System.out.println(i+"Thread name is +"+getName());
9
10 }
11
12 }
13
14 class ThreadDemo2
15 {
16
17 public static void main(String[] args) {
18
19 Demo2 d1 = new Demo2();
20 Demo2 d2 = new Demo2();
21
22 //d1.start();
23 //d2.start();
24 d1.run();
25 d2.run();
26
27 }
28
29 }
现在的线程明明就main一个线程,但是线程的名称还是之前线程对象初始化时候的名称:
如果我们这样写的话,以上两种无论开启线程与否,得到的线程名称都是一样的,也就是说这里有一个注意的地方就是线程的名称是在线程初始化的时候就已经定义了,我们如果响获取当前运行线程的名称的话,我们应该先获取当前的线程 ,然后获取当前线程的名称才对的。如何获取当前的线程呢?java当中为我们提供了一个静态的方法叫做currentThread()这个方法来获取当前运行的线程的名称,我们修改上述代码为:
1 class Demo2 extends Thread
2 {
3
4 public void run()
5 {
6
7 for(int i = 0; i<=10 ; i++)
8 System.out.println("I is :"+i+"Thread name is +"+Thread.currentThread().getName());//获取当前的线程
9
10 }
11
12 }
13
14 class ThreadDemo2
15 {
16
17 public static void main(String[] args) {
18
19 Demo2 d1 = new Demo2();
20 Demo2 d2 = new Demo2();
21
22 d1.run();
23 d2.run();
24
25 }
26
27 }
结果:
多线程在内存当中的表现形式:
多线程当中每个线程在栈当中都有属于自己的栈,相互之间栈互不影响。如图:
线程是进程在内存当中的进一步的划分。