为了演示多线程,我们用一个代码来展示多线程的效果:
public class App {
public static void main(String[] args) throws InterruptedException {
//子线程
new Thread(() -> {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":小强");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//主线程
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":旺财");
Thread.sleep(100);
}
}
}
流程图:
程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用Thread的对象的start方法,另外一个新的线程也启动了,这样,整个应用就在多线程下运行。 通过这张图我们可以很清晰的看到多线程的执行流程。
多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。
jvm虚拟机中,堆中放的是对象和数据,栈中放的是方法,方法区中放的是class类文件
public class MyThread extends Thread{
public MyThread(String name){
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("小强");
}
}
}
//调用
new MyThread("myThread").start
public class MyThread implements Runnable{
@Override
public void run() {
System.out.println("myThread");
}
}
//调用
Thread thread=new Thread(new MyThread());
thread.start()
我们更倾向于使用匿名内部类:
new Thread(() -> {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":小强");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个执行目标。所有的多线程
代码都在run方法里面。Thread类实际上也是实现了Runnable接口的类。
在启动多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread 对象的start()方法来运行多线程代码。
实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是继承Thread类还是实现
Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
总结:
实现Runnable接口比继承Thread类所具有的优势:
扩充:在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用
java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM其实在就是在操作系统中启动了一个进
程。
原文:https://www.cnblogs.com/jimlau/p/12463476.html