概述
创建线程的方法常用的有两种,一个是继承Thread类,另一个是实现Runnable接口,然后用Runnable对象创建Thread类。所以在日常使用过程中,不可避免的使用Thread类,本文通过查看Thread类源码的方式,查看Thread类的方法,以及方法的实现原理。
构造方法
自己阅读源码的方式通常是从构造方法看起,里面会进行一些成员变量的初始化,有些是值得注意的。
无参构造
为什么默认的线程名会使用Thread-x,这里就说明了为什么。
Runnable参数
使用Runbable对象创建线程时,会使用target参数。
Runnable参数+String参数
这里的String用来给线程命名。
其他构造方法
等等,这里不列举全了。
start()方法和run()方法的区别
根据文档介绍,这个方法的执行结果是会用两条线程同时运行。且不可以调用一个线程两次start方法。
run方法针对的是传入的Runnable对象,调用Runnable的run方法。那么可以看出,run方法并不会开辟一个新的线程,而只是运行run的方法体。所以总结来说,在启动线程的时候,需要使用start方法启动。
yield()方法和join()方法
yield()方法 暂停当前正在执行的线程对象,并执行其他线程。
官方翻译:给调度器一个提示,当前线程愿意让出占用的处理器。调度器可以忽略这个提示。
yield方法是一种启发式尝试(大雾),用于改善线程之间的相对进展,否则会过度利用CPU。 它的使用应与详细的分析和基准测试相结合,以确保它实际上具有所需的效果。
很少场景适合使用这个方法。 它可能对调试或测试目的很有用,它可能有助于重现因竞争条件而产生的错误。 在设计并发控制结构(例如java.util.concurrent.locks包中的结构)时,它也可能很有用。
yield()方法实例
class Run implements Runnable{
public static volatile boolean flag = true;
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + "开始执行");
while (flag){
for (int i = 0; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "执行了" + i + "次");
Thread.yield();
}
}
System.out.println(name + "执行完毕");
}
}
public class Entry2 {
public static void main(String[] args) {
Thread t1 = new Thread(new Run());
Thread t2 = new Thread(new Run());
t1.start();
t2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Run.flag = false;
}
}
实行结果
效果就是两个线程因为yield方法交替执行。
yield的使用场景
yield的作用就是暂时让出使用着的CPU,这样其他【就绪态】的线程就有机会占用这个CPU去执行。所以yield的使用场景多在,当前线程在进行耗时性的操作时(如IO操作),并且因为它的优先级较高,导致一些优先级较低的线程被分配的时间片更少,这样优先级低的线程就要等待更长时间才能完成操作,那么这时适当地调用几次yield方法让出CPU,让优先级低的线程多得到执行,这样才能高效的实现程序执行和响应。
join()方法
join()方法是指等待调用join()方法的线程执行结束,程序才会继续执行下去,这个方法适用于:一个执行程序必须等待另一个线程的执行结果才能够继续运行的情况。
官方翻译:等待线程死亡,调用此方法的行为与调用完全相同。
然后看一看join的具体实现,通过判断线程是否存活,一直调用wait()。
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}