线程常用的方法

线程中常用的几个方法:currentThread()方法、isAlive()方法、sleep()方法、getId()方法和yield()方法。

currentThread()方法

1)currentThread()方法可返回代码段正在被哪个线程调用的信息。如代码清单1所示。

代码清单1 返回线程调用信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class CurrentThread extends Thread {
public CurrentThread(){
System.out.println("构造方法的打印:"+Thread.currentThread().getName());
}
public void run(){
System.out.println("Run方法的打印:"+Thread.currentThread().getName());
}
}
public class Run{
public static void main(String[] args) {
// TODO Auto-generated method stub
CurrentThread myCurrentThread=new CurrentThread();
myCurrentThread.start();
//myCurrentThread.run();
}
}

运行结果如图1所示,构造方法被mian线程调用,而run方法被名称为Thread-0的线程调用。



图1 调用start()返回线程结果

当注释掉start()方法,启用myCurrentThread.run();运行结果如图2所示。



图2 直接调用run()返回线程结果

2)在比较复杂的情况下,对currentThread()应用,如代码清单2所示。

代码清单2 复杂的情况下currentThread()应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class CountOperate extends Thread {
public CountOperate(){
System.out.println("CountOpera---begin");
System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName());
System.out.println("this.getName()=" + this.getName());
System.out.println("CountOpera---end");
}
@Override
public void run() {
System.out.println("run---begin");
System.out.println("Thread.currentThread.getName()=" + Thread.currentThread().getName());
System.out.println("this.getName()=" + this.getName());
System.out.println("run---end");
}
}
public class CountOperateRun {
public static void main(String[] args) {
CountOperate c=new CountOperate();
Thread t1=new Thread(c);
t1.setName("A");
t1.start();
}
}

输出结果如图3所示。



图3 返回结果

在自定义线程类时,如果线程类是继承java.lang.Thread的话,那么线程类就可以使用this关键字去调用继承自父类Thread的方法,this就是当前的对象。
另一方面,Thread.currentThread()可以获取当前线程的引用,一般都是在没有线程对象又需要获得线程信息时通过Thread.currentThread()获取当前代码段所在线程的引用。
至于这里为什么两次this.getName都是Thread-0,因为this代表的是CountOpera这个对象,this.getName()其实就是最简单的方法调用,然而当前对象里面没有这个方法,又因为继承了Thread方法,所以它执行的就是Thread父类的方法,父类方法如下:

1
2
3
4
5
6
public final String getName() {
return String.valueOf(name);
}
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}

Thread-0就是上面init()方法将name的值设置进去。

isAlive()方法

1)方法isAlive()的功能是判断当前的线程是否处于活动状态。

代码清单3 isAlive()应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MyIsAlive extends Thread {
@Override
public void run() {
System.out.println("run=" + this.isAlive());
}
}
public class IsAliveRun {
public static void main(String[] args) throws InterruptedException {
MyIsAlive myIsAlive=new MyIsAlive();
System.out.println("begin=="+myIsAlive.isAlive());
myIsAlive.start();
//Thread.sleep(1000);
System.out.println("end=="+myIsAlive.isAlive());
}
}

运行结果如图4所示,"end=="+myIsAlive.isAlive()的运行结果是true,但此值是不确定的。打印true值是因为myIsAlive线程还没有执行完毕,所以输出为true。



图4 返回结果

去掉代码中注释,开启sleep()方法,运行结果如图5所示。"end=="+myIsAlive.isAlive()输出的结果为false,因为myIsAlive对象已经在1秒之内执行完毕。



图5 开启sleep()返回结果

2)在使用isAlive()方法时,如果将线程对象以构造参数的方式传递给Thread对象进行start()启动时,运行的结果和前面示例是有差异的。造成这样的差异的原因还是来之于Thread.currentThread()和this的差异。

代码清单4 测试一下上面结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class IsAliveOperate extends Thread {
public IsAliveOperate(){
System.out.println("IsAliveOperate---begin");
System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()="+Thread.currentThread().isAlive());
System.out.println("this.getName()="+ this.getName());
System.out.println("this.isAlive()="+ this.isAlive());
System.out.println("IsAliveOperate---end");
}
@Override
public void run() {
System.out.println("run---begin");
System.out.println("Thread.currentThread().getName()="+Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()="+Thread.currentThread().isAlive());
System.out.println("this.getName()="+ this.getName());
System.out.println("this.isAlive()="+ this.isAlive());
System.out.println("run---end");
}
}
public class IsAliveOperateRun {
public static void main(String[] args) {
IsAliveOperate c=new IsAliveOperate();
Thread t=new Thread(c);
System.out.println("main begin t isAlive = "+t.isAlive());
t.setName("A");
t.start();
System.out.println("main end t isAlive = "+t.isAlive());
}
}

尽管this与Thread.currentThread() 都可以获取到Thread的引用,但是在某种情况下获取到的引用是有差别的。



图6 运行结果

sleep()方法

1)方法sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。

代码清单5 sleep()休眠线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SleepThread extends Thread {
@Override
public void run() {
try {
System.out.println("run threadName="+this.currentThread().getName()+" begin");
Thread.sleep(2000);
System.out.println("run threadName="+this.currentThread().getName()+" end");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class SleepRun1 {
public static void main(String[] args) {
SleepThread t=new SleepThread();
System.out.println("begin ="+System.currentTimeMillis());
t.run();
System.out.println("end="+System.currentTimeMillis());
}
}

直接调用run()方法,运行结果如图7所示。



图7 直接调用run()方法

2)使用start()启动线程。

代码清单6 start()启动线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class SleepThread2 extends Thread {
@Override
public void run() {
try {
System.out.println("run threadName="+this.currentThread().getName()+" begin="+System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("run threadName="+this.currentThread().getName()+" end="+System.currentTimeMillis());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class SleepRun2 {
public static void main(String[] args) {
SleepThread2 t=new SleepThread2();
System.out.println("begin ="+System.currentTimeMillis());
t.start();
System.out.println("end="+System.currentTimeMillis());
}
}

由于mian线程与t线程时异步执行的,所以首先打印的信息为begin和end。而t线程时随后运行的,在最后两行打印run begin 和run end相关的信息。



图8 用start()启动线程

getId()方法

getId()方法的作用是取得线程的唯一标识。
代码清单7 获取id值

1
2
3
4
5
6
7
8
public class getIdThread {
public static void main(String[] args) {
Thread runThread=Thread.currentThread();
System.out.println(runThread.getName()+" "+runThread.getId());
}
}

从运行结果看线程名为mian,id为1.



图9 获取id

yield()方法

yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
代码清单8 取得运行时间,测试yield方法的使用效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class YieldThread extends Thread {
@Override
public void run() {
long beginTime =System.currentTimeMillis();
int count=0;
for(int i=0;i<50000000;i++){
//Thread.yield();
count=count+(i+1);
}
long endTime=System.currentTimeMillis();
System.out.println("用时:"+(endTime-beginTime)+"毫秒!");
}
}
public class YieldRun {
public static void main(String[] args) {
YieldThread thread=new YieldThread();
thread.start();
}
}

运行结果如题10 所示。



图10 CPU独占时间

去掉//Thread.yield();注释,再次运行,如图11所示。



图11 将CPU让给其他资源导致速度变慢

Java多线程编程核心技术源代码及PDF

Adhere to the original technology to share, your support will encourage me to continue to create!