为什么要掌握多线程
用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。对于多线程的重要性,相信也不需要过多的阐述,只要没有领悟透彻,面试官将会给予社会性的教育...别问我为什么知道!!
创建多线程的方式
关于多线程的创建方式,网上的文档五花八门,各有各的说法,有2、4、6种等等,有带返回值的也有线程池等;到底有多少种呢,关于这个的解答,Oracle的官方文档中早已给出了答复。官方网档链接
There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread. This subclass should override the run method of class Thread
-
方法一:实现Runnable接口
/** * Runnable方式实现多线程 */ public class RunnableStyle implements Runnable{ @Override public void run() { System.out.println("实现了Runable方法"); } public static void main(String[] args) { Thread thread = new Thread(new RunnableStyle()); thread.run(); } } -
方法二:继承Thread类
public class ThreadStyle extends Thread{ @Override public void run() { System.out.println("继承Thread类实现多线程"); } public static void main(String[] args) { new ThreadStyle().start(); } }
实现优劣
方法一(实现Runnable接口)更好
-
从代码架构考虑,run方法对应一个具体的任务,应该与线程的创建与运行等线程机制(即Thread类)解耦,从解耦性考虑
-
资源节约,每次一个新的任务都需要新建一个独立的线程(继承Thread类),用实现Runnable方法可以利用线程池等机制
-
用继承Thread类,因为Java不支持多继承,所以该线程无法继承其他类,对业务上比较麻烦
-
源码角度,实现Runnable有一个判断,调用传入的Run方法;继承Thread类的话,是重写了整个Run方法(见上述源码)
@Override public void run() { if (target != null) { target.run(); } }
思考(同时调用Runnable的run()和Thread的run()方法,会如何执行)
最终Thread方法会执行,从源码角度分析,虽然构造了Thread方法并传入了Runnable对象,但是因为Thread的实现方式又重写了run()方法,所以最终还是执行了Thread的重写run()方法。
public class BothRunnableThread {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("运行了Runnable方法");
}
}){
@Override
public void run() {
System.out.println("运行了Thread方法");
}
}.start();
}
}
总结
- 创建线程可以分为两类,Oracle官方文档也是这么说的;
- 准确地说,创建线程只有一种方式——构造Thread类,而实现线程的执行单元有两种方式
- 方法一:实现Runnable 接口的run方法,并把Runnable对象实例传给Thread类执行
- 方法二:重写Thread类的run方法(继承Thread类)