本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。
最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。
最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。
学习路线图
其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。
相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。
网络安全工具箱
当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。
项目实战
最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~
面试题
归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
今天主要是来了解Java线程Thread中的
run()
、start()
两个方法的执行有哪些区别,会给出一个简单的测试代码样例,快速理解两者的区别,再从源码层面去追溯start()
底层是如何最终调用Thread#run()
方法的,个人觉得这样的学习不论对面试,还是实际编程来说都是比较有帮助的。
进入正文~
学习目录
一、代码测试
执行Thread的run()、start()方法的测试代码如下:
public class MyThread {
public static void print() {
System.out.println("print...");
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println("执行print()方法的线程是:" + Thread.currentThread().getName());
print();
}
};
System.out.println("一、调用run()方法的线程是:" + Thread.currentThread().getName());
thread1.run();
Thread.sleep(1000);
System.out.println("二、调用start()方法的线程是:" + Thread.currentThread().getName());
thread1.start();
}
}
测试结果:
一、调用run()方法的线程是:main
执行print()方法的线程是:main
print...
main
二、调用start()方法的线程是:main
执行print()方法的线程是:Thread-0
print...
Thread-0
简单总结:
- run()方法调用和执行重写的代码块都是由main主线程来完成的;
- start()方法调用是有main()主线程来调用,但是重写的代码块是由
非main
主线程来执行的。
二、源码分析
2.1 run()方法
通过线程调用run()方法,这个其实很简单,比如前面测试代码执行run方法:
thread1.run();
Ctrl + 鼠标左键,进入到java.lang.Thread
的run()
方法的源码:
@Override
public void run() {
if (target != null) {
target.run();
}
}
再Ctrl + Alt + 鼠标左键,定位前面测试类MyThread中重写的run()方法
可以发现,直接就调用到重写的run()方法了,并且,你可以重复调用多次,而且每一次都是由main主线程调用run()方法,然后非main主线程,执行run()方法代码块
虽然run()方法也可以直接执行到重写的代码块,不过实际当中,按规范来说,不会直接调用run()执行,而是通过start()方法来开启线程,start()方法底层会判断线程的状态,开启线程,最终调用run()方法并结束线程状态,往后了解。
2.2 start()方法
Oracle JDK源码stat()
方法:
public class Thread implements Runnable {
...
private ThreadGroup group;
private volatile int threadStatus = 0;
...
public synchronized void start() {
//如果线程状态不是0-新建,则抛异常
if (threadStatus != 0)
throw new IllegalThreadStateException();
//将当前线程添加到线程组
group.add(this);
//线程是否开启,默认false-未开启
boolean started = false;
try {
//调用native本地方法(最终调用run()方法的核心入口)
start0();
//执行完start0,说明线程已正常启动
started = true;
} finally {
try {
if (!started) {
//线程启动失败,则从线程组中将该线程删除
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
...
}
}
}
难点和重点是调用的start0()
方法,这是一个native(本地方法/底层方法),源码:
//native本地方法,底层开启异步线程,由JVM创建并启动线程,并最终调用run()方法
private native void start0();
由于Oracle JDK对于native本地方法的源码隐藏了具体实现,可以去Open JDK官方或Github下载源码
以下载open jdk8最新的源码版本jdk8u60为例,需要下载jdk
和hotspot
两种源码来研究
- 下载
jdk8u60
源码
http://hg.openjdk.java.net/jdk8u/jdk8u60/jdk/file/935758609767
- 下载jdk8u60的
hotspot
源码
http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd
最后发现Open JDK官网下载实在是太慢了,而且还需要分别下载jdk8u60和jdk8u60_hotspot的源码
不过现在OpenJDK的源码已经放到GitHub,可以直接去GitHub下载,而且jdk源码和hotspot源码直接放一起了,省事,这里以下载jdk8-b60
示例,下载地址:
https://github.com/openjdk/jdk/releases/tag/jdk8-b60
下载完解压,主要关注jdk和hotspot这两个源码目录:
使用相关工具,比如Scource Insight
查看底层方法native stat0
具体源码实现
(教程)安装Scource Insight
(教程)使用Scource Insight打开OpenJDK源码
接下来通过Scource Insight查看底层方法start0是如何一步步,最终由主线程调用Thread#run()方法的源码分析过程
首先查看
源码文件:\jdk-jdk8-b60\jdk\src\share\native\java\lang\ Thread.c
关键源码:JVM_StartThread
static JNINativeMethod methods[] = {
{"start0", "()V", (void \*)&JVM_StartThread},//JVM开启线程的主入口
{"stop0", "(" OBJ ")V", (void \*)&JVM_StopThread},
{"isAlive", "()Z", (void \*)&JVM_IsThreadAlive},
{"suspend0", "()V", (void \*)&JVM_SuspendThread},
{"resume0", "()V", (void \*)&JVM_ResumeThread},
{"setPriority0", "(I)V", (void \*)&JVM_SetThreadPriority},
{"yield", "()V", (void \*)&JVM_Yield},
{"sleep", "(J)V", (void \*)&JVM_Sleep},
{"currentThread", "()" THD, (void \*)&JVM_CurrentThread},
{"countStackFrames", "()I", (void \*)&JVM_CountStackFrames},
{"interrupt0", "()V", (void \*)&JVM_Interrupt},
{"isInterrupted", "(Z)Z", (void \*)&JVM_IsInterrupted},
{"holdsLock", "(" OBJ ")Z", (void \*)&JVM_HoldsLock},
{"getThreads", "()[" THD, (void \*)&JVM_GetAllThreads},
{"dumpThreads", "([" THD ")[[" STE, (void \*)&JVM_DumpThreads},
{"setNativeName", "(" STR ")V", (void \*)&JVM_SetNativeThreadName},
### 一、网安学习成长路线图
网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
![在这里插入图片描述](https://img-blog.csdnimg.cn/aa7be04dc8684d7ea43acc0151aebbf1.png)
### 二、网安视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
![在这里插入图片描述](https://img-blog.csdnimg.cn/f0aeee2eec7a48f4ad7d083932cb095d.png)
### 三、精品网安学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
![在这里插入图片描述](https://img-blog.csdnimg.cn/078ea1d4cda342f496f9276a4cda5fcf.png)
### 四、网络安全源码合集+工具包
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e54c0bac8f3049928b488dc1e5080fc5.png)
### 五、网络安全面试题
最后就是大家最关心的网络安全面试题板块
![在这里插入图片描述](https://img-blog.csdnimg.cn/15c1192cad414044b4dd41f3df44433d.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/b07abbfab1fd4edc800d7db3eabb956e.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**