Java 线程有哪些常用方法?
# Java 线程如何启动?如何终止?
线程随着start()
方法的调用而启动,随着run()
方法调用结束而终止。
但是这其中还会涉及到线程的构造、中断、暂停、恢复,我们来一一看下。
# 构造线程
在运行一个线程之前 肯定要先构造一个线程对象,构造线程对象需要提供所需属性:如线程所属组,线程优先级,是否deamon等。
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
//1.设置线程名
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
//2.设置线程的线程组,如果未指定,则此线程的线程组为当前初始化线程的线程组
Thread parent = currentThread();
...
if (g == null) {
//这里有一段注释说,安卓不支持SecurityManager,所以删除了相关代码
g = parent.getThreadGroup();
}
//所属线程组未启动线程计数+1
g.addUnstarted();
this.group = g;
//3.设置线程的其他属性
//线程是否是守护线程以及优先级都继承自当前线程
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
this.target = target;
//4.调用init2 执行剩余初始化操作
init2(parent);
//5.设置线程的堆栈大小。但是否生效要看虚拟机。那么在art虚拟机上是否生效呢,我们后续再说
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
//6.设置当前线程id
tid = nextThreadID();
}
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
34
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
34
到这里为止,我们的thread就已经初始化完毕了。在堆内存中等待这被执行start()
方法开始运行。
# 启动线程
调用start()
方法开始启动线程。
# 理解中断
如果线程需要执行一个长时间任务,就可能需要能中断线程。中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行。
中断可以理解为线程的一个标志位属性,调用interrupt()
方法中断线程仅仅是把中断标志位置为true
,线程可以通过检查自身的标志位来判断是否被中断了。
另外还有两点需要注意的:
- 如果线程处于终结状态,即使线程被中断过,其中断标识位依然是false
- 许多声明抛出
InterruptException
的方法(如Thread.sleep(long millis)),在抛出InterruptException
之前会将中断标识位置为false。
# 已不建议使用的方法:suspend()
,resume()
,stop()
suspend()
,resume()
,stop()
完成了线程的暂停、恢复、停止。但是这些方法过期了 不建议继续使用,原因是:
suspend()
暂停线程是不会释放资源(比如锁),而是占着资源入睡 ,这样容易引发死锁stop()
终止线程时没有给线程清理资源的机会,导致程序运行在不确定状态
取而代之的是wait()
和notify()/notifyAll()
。
# 安全的终止线程
可以通过interrupt()
或者标识位来优雅的停止线程。
public class MyRunner implements Runnable {
private volatile boolean on = true;
public void run() {
while(on){
System.out.println("Running...");
}
System.out.println("Stoped!");
}
public void cancel(){
on = false;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
通过标识位来停止线程
public class ShutdownThread {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunner().start();
t1.cancel();
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
通过interrupt()
来停止线程
public class ShutdownThread {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunner().start();
t1.interrupt();
}
}
1
2
3
4
5
6
2
3
4
5
6
编辑 (opens new window)
上次更新: 2022/05/19, 21:26:01