两者都创建线程的方式,不同之处在于前者是类,后者是接口。使用的时候重写他们即可。
预热:操作系统的知识
想象此时有一条马路,走的人多了道路开始变得堵塞,如果拓宽为多车道即可解决该问题。
这便是多线程的例子。进程与线程是老生常谈的话题,进程是静态的程序运行时的过程,而一个进程可以包含若干个线程,最少的情况就是只有一个主线程。在java中还会有一个gc线程用于回收资源。
线程是cpu调度和执行的基本单位,而很多多线程是模拟出来的,并不是真正的多线程,只是切换的足够快,产生了多线程的错觉。
Thread方法:继承Thread类
流程如下:
- 写一个类继承Thread类;
- 重写run方法
- 最后new一个它的对象,并使用这个对象调用start方法开启线程。
而我们要运行的内容就放在run方法内。
public class TestThread1 extends Thread {
//重写Thread类的run方法,将要执行在线程中的任务放入其中
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("reading..."+i);
}
}
public static void main(String[] args) {
//创建一个TestThread1对象的示例
TestThread1 testThread1 = new TestThread1();
//调用start方法开启线程
testThread1.start();
//如果我们调用的是run方法,就会先执行testThread1的内容,再执行主线程的
//这样就违背了我们要做多线程的想法
for (int i = 0; i < 2000; i++) {
System.out.println("studying..."+i);
}
}
}
如果直接调用run方法,相当于只有主线程在运行,而调用start方法时会开辟一个新的子线程去执行内部的run方法。
Runnable方法:实现Runnable接口
流程如下:
- 创建一个类实现Runnable接口;
- 重写run方法;
- 创建一个线程对象,将我们创建的类放入其中,执行start方法以启动线程。
public class TestThread2 implements Runnable {
//重写Runnable接口的run方法,将要执行在线程中的任务放入其中
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("reading..."+i);
}
}
public static void main(String[] args) {
//创建一个TestThread2对象的示例
TestThread2 testThread2 = new TestThread2();
//new一个线程对象,传入Runnable示例并调用start方法执行
new Thread(testThread2).start();
for (int i = 0; i < 2000; i++) {
System.out.println("studying..."+i);
}
}
}
两者关系
Thread类同样也实现了Runnable接口。通过上面的例子可知,当我们使用Runnable方法创建线程时,同样需要使用Thread来执行。前人总结如下:
无论使用两种方法的哪一种,都会new Thread,然后执行我们重写的run方法。
用法上,如果有复杂的线程操作,就继承Thread;如果只是简单的执行一个任务,就实现runnable。