最近温习了下线程的相关知识点,在这里和大家分享下。
刚开始接触java的伙伴,可能对线程什么的比较迷糊,茫茫然死记硬背了一点,其中的知识总是感觉晕晕乎乎,好像懂了又好像没懂。
想要理解java线程的知识点,首先要明白进程与线程的含义,下面是摘抄的线程与进程的说明。
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
用java中一直在用的虚拟机来说,你启动一个main()方法,就是启动了一个JVM进程,而这个进程中包含守护线程(垃圾回收)与普通的线程(main方法中之行的任务)
刚开始接触java线程,我们知道java线程两种常见的创建方式,继承Thread与实现Runnable。如果你不明白的话,那就提前先死记住吧,这个java语言就是这么规定的,没啥好说的,接触久了自然就习惯了。
下面实现写两个简单的线程:
继承Thread
package com.example.demoproject;
public class ThreadEx extends Thread{
public ThreadEx(String name) {
super(name);
}
/**
* 重写run()方法
*/
@Override
public void run() {
System.out.println("运行方式"+this.getName()+" ThreadEx方法名称:"+Thread.currentThread().getName()+" Thread id信息:"+Thread.currentThread().getId());
}
}
实现Runable方法
package com.example.demoproject;
public class ThreadRun implements Runnable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ThreadRun(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("ThreadRun方法名称:"+Thread.currentThread().getName()+" Thread id信息:"+Thread.currentThread().getId());
}
}
接触线程创建之后,我们知道线程有两种启动方式:start()与run(),那这两种方式有什么区别呢?我们来运行下程序看看。
package com.example.demoproject;
public class ThreadTest {
public static void main(String[] args) {
ThreadRun runThread = new ThreadRun("runThread");
ThreadEx threadEx1 = new ThreadEx("start");
ThreadEx threadEx2 = new ThreadEx("run");
runThread.run();
threadEx1.start();
threadEx2.run();
}
}
程序运行结果:
ThreadRun方法名称:main Thread id信息:1
运行方式run ThreadEx方法名称:main Thread id信息:1
运行方式start ThreadEx方法名称:start Thread id信息:11
Process finished with exit code 0
大家可以看到总共有两个线程,线程的id分别是1和11,runThread实现了run()方法,不过是没有start()方法的哟。
我们可以看到,main()方法的线程id是1,使用run()方法启动的两个线程,线程的id也是1,。这说明了什么?使用run()方法并没有新建线程!
而是用start()方法启动的线程,线程id是11,和main()不是同一个线程,很明显是启动了一个新的线程。
所以,使用run()方法运行线程,就是相当于创建了一个对象,然后调用了对象的一个方法,并没有创建线程的操作,只有使用start()启动的时候才会新建线程。
当然,现实编码中很少去自己创建线程的,因为频繁的创建和销毁线程对服务来说也是不小的开销。我们一般调用线程池中的线程为我们服务。
对了,大家看下运行结果,有没有感觉什么不对的地方?
比如:我代码里明明是先写的start()方法,可运行的时候怎么start()方法在最后了?为什么不是按顺序来呢?大家可以试下,发现大部分情况都是和我的运行结果一致。
这里来说的话,首先,start()方法会重建一个线程,这个操作无疑是会耗时的,但是这个并不影响main()方法的运行,所以等新线程创建完毕,main()方法已经运行到下面的代码了,start()方法之行自然会显得慢一些。