juc07 创建线程
创建线程
JAVA中线程被封装成Thread对象。JDK API中有对Thread的说明,连创建方式都有。
自定义线程有两种方式:
- 继承Thread
- 实现Runable接口
从打印结果是否是不同线程运行来验证多线程执行。
主线程代码在main方法中,自定义线程方法代码在run方法中。
两种创建方式的区别:
- Thread 的代码是存在子类当中;
- Runable方式的代码是的实现接口的子类当中,还避免了单继承的问题。
一、继承 Thread 方式
这种方式最简单,需要三个步骤:
- 继承 Thread 类
- 重写 run 方法,run方法要看成一个入口点。
- 调用 start 方法来执行自定义线程
实现代码:
1 | public class TestThread extends Thread { |
结果
会交替打印 run 和 main 证明CPU执行线程时是交替进行的。而且这种交替是随机性的。
说明:run
方法中写上自定义线程要执行的程序,而调用 start
才是真正表示开始执行这条自定义线程。
理解: main
是程序默认线程入口,run
是自定义程序入口,和 main
等价。
但是 main
是程序开启的,run
是由用户开启的。
注意事项
- 注意this
如果继承自Thread类,可以直接使用this关键字来调用Thread类中的方法,如getName方法,因为是继承所以可以直接使用方法。
- 注意super
继承Thread后,也可以直接调用父类的方法给自己用,而不需要.currentThread.方法。
如super(name); 直接调用构造方法重命名线程。
二、Runable 方式
这种方式业务类必须实现Runnable
接口,并将业务类所创建的对象传入 Thread
对角中去。
由于对象只有一份,所以多个 Thread
对象操作的是同一个对象,所以就会产生共享数据的问题,即,不安全问题的产生。
代码实现
1 | public class TestSun { |
多写一个例子:
1 | public class TestSun implements Runnable { |
理解:例用实现Runnable还有一个好处就是,我不同的类,我可以有不同的run实现方法,
Runable 共享资源问题
下面代码的执行结果是:输出 50次。如果使用继承Thread的方式的话,会被执行200次。
原就是就因为 Test 对象实际上被所有线程所共享,所有线程所操作的时同一个对象。
如果使用Thread方式,给变量i设为静态也可以做到执行50次,但是静态的生命周期太长了,不推荐。
这个例子为了说明 Thread 和 Runable 的区别。
而为什么 Thread 对执行多次,是因为继承的Thread 后,每new 一次,就是创建的一个新对象,每个对象都是一分独立的副本,并不是同一个对象。
1 | package com.liukai.thread; |
区别
runnable 和 继承Thread 方式的区别
这种非常重要的概念,一定要明白。关系到线程的执行方式。
- 继承Thread类方式:线程到码存放在Thread子类的run方法中。即继承了Thread类的自定义线程类的run方法中。
- 实现Runnable接口方式:线程代码存在接口的子类的run方法中。注意是接口的子类的run方法中,不是实现类的run方法中。
第2种方式最常用。
优点:
- 避免单继承的局限性。
- 多个业务代码可以有不同的代码存放区。