开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
策略模式在Thread和Runnable中的应用
Runnable接口最重要的方法—–run方法,使用了策略者模式将执行的逻辑(run方法)和程序的执行单元(start0方法)分离出来,使用户可以定义自己的程序处理逻辑,更符合面向对象的思想。
Thread的构造方法
- 创建线程对象Thread,
默认有一个线程名,以Thread-开头,从0开始计数,如“Thread-0、Thread-1、Thread-2 …” - 如果没有传递Runnable或者没有覆写Thread的run方法,
该Thread不会调用任何方法 - 如果传递Runnable接口的实例或者覆写run方法,则
会执行该方法的逻辑单元(逻辑代码) - 如果构造线程对象时,未传入ThreadGroup,
Thread会默认获取父线程的ThreadGroup作为该线程的ThreadGroup,此时子线程和父线程会在同一个ThreadGroup中 - stackSize可以
提高线程栈的深度,放更多栈帧,但是会减少能创建的线程数目 - stackSize默认是0,
如果是0,代表着被忽略,该参数会被JNI函数调用,但是注意某些平台可能会失效,可以通过“-Xss10m”设置
具体的介绍可以看Java的API文档
/*下面是Thread 的部分源码*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
↓ ↓ ↓
↓ ↓
↓
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
↓ ↓ ↓
↓ ↓
↓
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
//中间源码省略
this.target = target;//①
}
/* What will be run. */
private Runnable target; //Thread类中的target属性
@Override
public void run() {
if (target != null) { //②
target.run();
}
}
源码标记解读:
1、如果Thread类的构造方法传递了一个Runnable接口对象
①那么该接口对象将被Thread类中的target属性所保存。
②在start()方法执行的时候会调用Thread类中的run()方法。因为target不为null, target.run()就去调用实现Runnable接口的子类重写的run()。
2、如果Thread类的构造方传没传Runnable接口对象
①Thread类中的target属性保存的就是null。
②在start()方法执行的时候会调用Thread类中的run()方法。因为target为null,只能去调用继承Thread的子类所重写的run()。
JVM一旦启动,虚拟机栈的大小已经确定了。但是如果你创建Thread的时候传了stackSize(该线程占用的stack大小),该参数会被JNI函数去使用。如果没传这个参数,就默认为0,表示忽略这个参数。注:stackSize在有一些平台上是无效的。