多线程的两种实现方法分析
什么是进程,线程?
进程是一个系统分配资源的基本单位。一个应用程序被启动,就会被加载进入内存(cpu),此时在内存中的应用程序就是进程,一个应用程序可以有多个进程同时运行在内存中。在早期的系统中 ,只有进程,但从创建进程到不同进程之间的切换所花费的资源开销很大,所以为了降低这种开销,我们引入了线程的概念。线程是系统独立运行的单元,它在创建,不同线程之间切换的开销都远小于进程,线程不拥有资源(仅拥有少量保证线程基本运行的资源)。
java中实现多线程的两种方法
1.继承thread类
package test;
public class ThreadDemo1 extends Thread {
public static void main(String[] args) {
ThreadDemo1 t1=new ThreadDemo1();
t1.start();
}
@Override
public void run() {
System.out.println("ThreadDemo1 is running");
}
}
2.实现Runnable接口
package test;
public class ThreadDemo2 implements Runnable {
public static void main(String[] args) {
ThreadDemo2 t2=new ThreadDemo2();
Thread t=new Thread(t2);
t.start();
}
public void run()
{
System.out.println("ThreadDemo2 is running");
}
}
这两种方法的都是由调用start()启动线程,然后执行相应的run()方法。run()相当于一个容器包含了你要做的事。
在底层的区别?
先看源码,只选取了有用的
Thread源码`
public class Thread implements Runnable{
private Runnable target;
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public void run() {
if (target != null) {
target.run();
}
}
}
Runnable接口的源码
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
从上面可以看出,Thread类限制了传参必须是runnable实现类类型,所有在实现Runnable接口的方式中本质上还是调用的Thread.run(),不过run()方法再调用target.run()而已。而对于继承Thread类的方式则是直接重写了run()方法。因为调用start()方法的时候默认调用Thread.run()方法,所有两种方法的本质都是调用了Thread.run()方法。
那么为什么还需要Runnable接口?
它大概有两个作用
1.限制Thread类的形参类型。因为在实现Runnable接口的方式,我们不知道要调用的run()方法在哪,所以需要限制Runnable实现类类型,这样Thread类才能知道在哪执行run().
2.使run()方法抽象,强制实现类重写。
在java中,类只能单继承,但是接口可以多继承,所以这也是其中的原因之一。从两种方式的对比我们可以知道,无论使用那种方式,最终都要回归到Thread.run(),所以没有Thread,Runnable就起不到任何作用!