Java多线程编程-Thread API
Thread是Java实现多线程的关键类,Thread提供了先关的API,我们来说说相关的API,就从我们使用最多的开始说起。
Thread.currentThread()
currentThread():返回对当前正在执行的线程对象的引用
源码:
//调用native的方法
public static native Thread currentThread();
我们都知道,Java的程序主入口是main方法,会默认启动一个Main线程进行运行,如下代码:
public class ThreadApiCurrentThreadV1 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}
}
运行结果
我们知道Thread会实现Runnable接口的run()方法,我们启动一个线程是使用start()方法。
我们看看run()方法和start()方法他们调用的线程就是是哪一个线程?上代码:
public class ThreadApiCurrentThreadV2 extends Thread {
public ThreadApiCurrentThreadV2() {
System.out.println("current thread name:" + Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("current thread name:" + Thread.currentThread().getName());
}
}
运行代码:
public class ThreadApiCurrentThreadV2Main {
public static void main(String[] args) {
ThreadApiCurrentThreadV2 threadApiCurrentThreadV2 = new ThreadApiCurrentThreadV2();
threadApiCurrentThreadV2.run();
}
}
运行结果为:
由上面的运行可以看出,构造ThreadApiCurrentThreadV2 的是主线程main,调用run()方法也是main方法,由此可以得到在运行线程的时候,不会另开一个线程去运行,就和普通的类方法一样。
我们使用jconsole也可以看出,如图
只有一个main线程。
运行start()方法,看看运行结果
现在会有一个新的线程为Thread-0,我们来看看jconsole的线程
会有一个新的Thread-0的线程在运行
由此可以得出结论:
1.java运行的时候,会有一个主线程main
2.在调用Thread的run方法时,不会创建一个新的线程去执行,就相当于普通对象调用方法一样
3.在调用Thread的start方法时,才会创建一个新的线程去执行run方法中的代码块
Thread.isAlive()方法
isAlive():测试此线程是否仍然存在。如果线程已经启动但尚未死亡,则该线程是活动的
源码:
public final native boolean isAlive();
在进行多线程的情况下,代码的顺序不会按照顺序执行,线程的运行是随机(获取CPU的执行权)
public class ThreadIsAliveV1 extends Thread {
@Override
public void run() {
System.out.println("this is a test alive api");
}
}
运行如下代码:
public class ThreadIsAliveV1Main {
public static void main(String[] args) {
ThreadIsAliveV1 threadIsAliveV1 = new ThreadIsAliveV1();
System.out.println("threadIsAliveV1 is alive:" + threadIsAliveV1.isAlive());
threadIsAliveV1.start();
System.out.println("threadIsAliveV1 is alive:" + threadIsAliveV1.isAlive());
}
}
运行结果:
这里第二句输出也true,但是这行代码是start()方法之后运行的啊?怎么还在活动状态呢?这个值是不确定的,有可能执行完了,也有可能没有执行完。
我们可以将主线程睡眠10秒看看结果,start()方法添加如下代码:
Thread.sleep(10000);
在看看結果:
这里讲会得到false,说明线程已经执行完成了。执行如图所示:
Thread.sleep()方法
sleep():根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数。该线程不会失去任何监视器的所有权。
源码:
public static native void sleep(long millis) throws InterruptedException;
我们通过调用run方法和start方法进行测试sleep方法
调用run方法:
public class ThreadSleepApiV1 extends Thread {
@Override
public void run() {
try {
System.out.println("current thread:" + this.currentThread().getName());
Thread.sleep(2000);
System.out.println("end current thread:" + this.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行代码:
public class ThreadSleepApiV1Main {
public static void main(String[] args) {
ThreadSleepApiV1 threadSleepApiV1 = new ThreadSleepApiV1();
System.out.println("start timestamp:" + System.currentTimeMillis());
threadSleepApiV1.run();
System.out.println("end timestamp:" + System.currentTimeMillis());
}
}
运行结果:
上面的时间是同步的运行的,相隔2000毫秒。
调用start方法:
public class ThreadSleepApiV2 extends Thread {
@Override
public void run() {
try {
System.out.println("current thread:" + this.currentThread().getName() + ",begin time:" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("end current thread:" + this.currentThread().getName() + ",end time:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行代码:
public class ThreadSleepApiV1Main {
public static void main(String[] args) {
ThreadSleepApiV2 threadSleepApiV2 = new ThreadSleepApiV2();
System.out.println("start timestamp:" + System.currentTimeMillis());
threadSleepApiV2.start();
System.out.println("end timestamp:" + System.currentTimeMillis());
}
}
运行结果:
由运行结果可以看出,main和Thread-0是异步运行的,先输入了main线程中的时间,在输出Thread-0执行run的时间。
Thread.getId()方法
getId():返回此线程的标识符。线程ID是创建该线程时生成的正long型数。线程ID是唯一的,并且在其生命周期内保持不变。当线程终止时,可以重新使用该线程ID。
源码:
public long getId() {
return tid;
}
现在在创建的时候,就会对id进行设置,是通过一个同步的方法进行,同步的方法为:
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
我们创建两个线程看看获取的id变化
public class ThreadIdV1 extends Thread {
@Override
public void run() {
System.out.println("id v1");
}
}
public class ThreadIdV2 extends Thread {
@Override
public void run() {
System.out.println("id v2");
}
}
运行代码:
public class ThreadIdVMain {
public static void main(String[] args) {
ThreadIdV1 threadIdV1 = new ThreadIdV1();
System.out.println(threadIdV1.getId());
threadIdV1.start();
ThreadIdV2 threadIdV2 = new ThreadIdV2();
System.out.println(threadIdV2.getId());
threadIdV2.start();
}
}
运行结果:
main线程的id为1,可以在运行代码加入代码
System.out.println(Thread.currentThread().getId());
将输出1.
总结
1.调用currentThread()方法在线程中引入线程的话,Thread.currentThread()和this所获取会有所差异,可以实验一下。