1.概述
java的JVM允许程序运行多个线程.使用java.lang.Thread来表示线程.一个线程都直接或间接的继承于Thread类,即每个线程的对象要么是Thread的实例,要么是其子类的实例.
2.Thread类的特性
- 每个线程都是通过某个特定的Thread对象的run方法来完成操作的,run()被称为线程执行体.
- 通过该线程对象的start()方法启动该线程,而非直接调用run方法(直接调用run()).
- 调用start()有两方面作用 : 启动该线程,调用run()方法.
- 要想实现多线程,则需要在主线程上创建新的线程对象.
3.方式1 : 继承Thread类
(1). 设计一个类并继承于Thread类.
(2). 重写Thread类的run()方法.
(3). 在主线程创建该子类的对象.
(4). 该对象调用start()启动线程.
例子 :
public class MulThread { public static void main(String[] args) { A a = new A(); a.start(); for (int i = 0; i <= 100 ; i++) { if (i % 2 == 0) { System.out.println(Thread.currentThread().getName() + "\t" + i); } } } } class A extends Thread{ public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 == 1) { System.out.println(Thread.currentThread().getName() + "\t" + i); } } } } 控制台 : Thread-0 1 main 0 main 2 Thread-0 3 main 4 Thread-0 5 main 6 Thread-0 7 main 8 Thread-0 9 main 10 略
4.方式2 : 实现Runnable接口
正儿八经的写法 :
(1). 创建一个实现Runnable接口的实现类.
(2). 实现接口的run()方法,线程要执行的操作,在该方法体中.
(3). 创建这个实现类的对象.
(4). 将该对象作为参数传递到Thread类的构造器,创建Thread类的对象.
(5). 通过Thread类的对象调用start()方法,启动线程,运行当前线程的run()方法.
例子 : 使用匿名实现类的匿名对象.
注 : IDEA快捷键 : 重写(Override) : Ctrl+o
实现接口(implements) : Ctrl+i
public class RunnableTest { public static void main(String[] args) { //创建匿名实现类的匿名对象 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 100; i++) { if (i % 2 == 0) { System.out.println(Thread.currentThread().getName() + "\t" + i); } } } }).start(); for (int i = 0; i <= 100; i++) { if (i % 2 == 1){ System.out.println(Thread.currentThread().getName() + "\t" + i); } } } } 控制台 : Thread-0 0 main 1 Thread-0 2 main 3 Thread-0 4 main 5 Thread-0 6 main 7 Thread-0 8 main 9 Thread-0 10 main 11 略
5.两种方式对比
(1). 共同点 :
- 启动线程,都调用的是Thread类的start().
- 创建的线程对象,都是Thread类的实例或其子类的实例.
(2). 不同点 :
- 一个是类的继承,一个是类的实现.
(3). 使用Runnable接口的好处 :
- 实现的方式避免了单继承的局限性.
- 更适合处理有共享数据的问题.(Thread类的实参都引用同一个实现类)
- 实现了代码和数据的分离.
(4). 明明调用的是Thread类的start(),为什么执行的是实现类实现的run()方法呢?
看源码 : Thread类的对象调用start()启动线程,调用Thread类的run()方法,Thread类有私有属性private Runnable target,target指向传入的实参(实现类)(此时再次体现了多态,接口类型的引用指向了实现类的对象),if(target !=null),那么调用的是target的run()方法.