java线程的常用方法
Posted 久伴兔兔宝宝
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java线程的常用方法相关的知识,希望对你有一定的参考价值。
java线程的常用方法
编号 | 方法 | 说明 |
---|---|---|
1 | public void start() |
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 |
2 | public void run() |
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 |
3 | public final void setName(String name) |
改变线程名称,使之与参数 name 相同。 |
4 | public final void setPriority(int priority) |
更改线程的优先级。 |
5 | public final void setDaemon(boolean on) |
将该线程标记为守护线程或用户线程。 |
6 | public final void join(long millisec) |
等待该线程终止的时间最长为 millis 毫秒。 |
7 | public void interrupt() |
中断线程。 |
8 | public final boolean isAlive() |
测试线程是否处于活动状态。 |
9 | public static void yield() |
暂停当前正在执行的线程对象,并执行其他线程。 |
10 | public static void sleep(long millisec) |
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。 |
11 | public static Thread currentThread() |
返回对当前正在执行的线程对象的引用。 |
一:静态方法
(1)currentThread()方法
currentThread()方法可以返回代码段正在被哪个线程调用的信息。
1
2
3
4
5
|
public class Run1{ public static void main(String[] args){ System.out.println(Thread.currentThread().getName()); } } |
(2)sleep()方法
方法sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
sleep方法有两个重载版本:
1
2
|
sleep( long millis) //参数为毫秒 sleep( long millis, int nanoseconds) //第一参数为毫秒,第二个参数为纳秒 |
sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。
但是有一点要非常注意,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用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
27
28
29
30
31
32
|
public class Test { private int i = 10 ; private Object object = new Object(); public static void main(String[] args) throws IOException { Test test = new Test(); MyThread thread1 = test. new MyThread(); MyThread thread2 = test. new MyThread(); thread1.start(); thread2.start(); } class MyThread extends Thread{ @Override public void run() { synchronized (object) { i++; System.out.println( "i:" +i); try { System.out.println( "线程" +Thread.currentThread().getName()+ "进入睡眠状态" ); Thread.currentThread().sleep( 10000 ); } catch (InterruptedException e) { // TODO: handle exception } System.out.println( "线程" +Thread.currentThread().getName()+ "睡眠结束" ); i++; System.out.println( "i:" +i); } } } } |
输出结果:
从上面输出结果可以看出,当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。
注意,如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出。当线程睡眠时间满后,不一定会立即得到执行,因为此时可能CPU正在执行其他的任务。所以说调用sleep方法相当于让线程进入阻塞状态。
(3)yield()方法
调用yield方法会让当前线程交出CPU权限,让CPU去执行其他的线程。它跟sleep方法类似,同样不会释放锁。但是yield不能控制具体的交出CPU的时间,另外,yield方法只能让拥有相同优先级的线程有获取CPU执行时间的机会。
注意,调用yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,这一点是和sleep方法不一样的。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class MyThread extends Thread{ @Override public void run() { long beginTime=System.currentTimeMillis(); int count= 0 ; for ( int i= 0 ;i< 50000000 ;i++){ count=count+(i+ 1 ); //Thread.yield(); } long endTime=System.currentTimeMillis(); System.out.println( "用时:" +(endTime-beginTime)+ " 毫秒!" ); } } public class Run { public static void main(String[] args) { MyThread t= new MyThread(); t.start(); } } |
执行结果:
1
|
用时: 3 毫秒! |
如果将 //Thread.yield();
的注释去掉,执行结果如下:
1
|
用时: 16080 毫秒! |
二:对象方法
(1)start()方法
start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。
(2)run()方法
run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要执行的任务。
(3)getId()
getId()的作用是取得线程的唯一标识
代码:
1
2
3
4
5
6
|
public class Test { public static void main(String[] args) { Thread t= Thread.currentThread(); System.out.println(t.getName()+ " " +t.getId()); } } |
输出:
1
|
main 1 |
(4)isAlive()方法
方法isAlive()的功能是判断当前线程是否处于活动状态
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class MyThread extends Thread{ @Override public void run() { System.out.println( "run=" + this .isAlive()); } } public class RunTest { public static void main(String[] args) throws InterruptedException { MyThread myThread= new MyThread(); System.out.println( "begin ==" +myThread.isAlive()); myThread.start(); System.out.println( "end ==" +myThread.isAlive()); } } |
程序运行结果:
1
2
3
|
begin == false run= true end == false |
方法isAlive()的作用是测试线程是否偶处于活动状态。什么是活动状态呢?活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。
有个需要注意的地方
1
|
System.out.println( "end ==" +myThread.isAlive()); |
虽然上面的实例中打印的值是true,但此值是不确定的。打印true值是因为myThread线程还未执行完毕,所以输出true。如果代码改成下面这样,加了个sleep休眠:
1
2
3
4
5
6
7
|
public static void main(String[] args) throws InterruptedException { MyThread myThread= new MyThread(); System.out.println( "begin ==" +myThread.isAlive()); myThread.start(); Thread.sleep( 1000 ); System.out.println( "end ==" +myThread.isAlive()); } |
则上述代码运行的结果输出为false,因为mythread对象已经在1秒之内执行完毕。
(5)join()方法
在很多情况下,主线程创建并启动了线程,如果子线程中药进行大量耗时运算,主线程往往将早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据中的值,就要用到join()方法了。方法join()的作用是等待线程对象销毁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class Thread4 extends Thread{ public Thread4(String name) { super (name); } public void run() { for ( int i = 0 ; i < 5 ; i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args) throws InterruptedException { // 启动子进程 new Thread4( "new thread" ).start(); for ( int i = 0 ; i < 10 ; i++) { if (i == 5 ) { Thread4 th = new Thread4( "joined thread" ); th.start(); th.join(); } System.out.println(Thread.currentThread().getName() + " " + i); } } } |
执行结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
main 0 main 1 main 2 main 3 main 4 new thread 0 new thread 1 new thread 2 new thread 3 new thread 4 joined thread 0 joined thread 1 joined thread 2 joined thread 3 joined thread 4 main 5 main 6 main 7 main 8 main 9 |
由上可以看出main主线程等待joined thread线程先执行完了才结束的。如果把th.join()这行注释掉,运行结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
main 0 main 1 main 2 main 3 main 4 main 5 main 6 main 7 main 8 main 9 new thread 0 new thread 1 new thread 2 new thread 3 new thread 4 joined thread 0 joined thread 1 joined thread 2 joined thread 3 joined thread 4 |
(6)getName和setName
用来得到或者设置线程名称。
(7)getPriority和setPriority
用来获取和设置线程优先级。
(8)setDaemon和isDaemon
用来设置线程是否成为守护线程和判断线程是否是守护线程。
守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。
在上面已经说到了Thread类中的大部分方法,那么Thread类中的方法调用到底会引起线程状态发生怎样的变化呢?下面一幅图就是在上面的图上进行改进而来的:
以上是关于java线程的常用方法的主要内容,如果未能解决你的问题,请参考以下文章