Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉默王二
Jmx Java
提交
40a09696
J
Jmx Java
项目概览
沉默王二
/
Jmx Java
9 个月 前同步成功
通知
160
Star
18
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
Jmx Java
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
40a09696
编写于
7月 17, 2023
作者:
沉默王二
💬
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
线程优先级
上级
1a88db4e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
130 addition
and
148 deletion
+130
-148
README.md
README.md
+0
-2
docs/thread/thread-group-and-thread-priority.md
docs/thread/thread-group-and-thread-priority.md
+129
-139
docs/thread/thread-state-and-method.md
docs/thread/thread-state-and-method.md
+1
-7
未找到文件。
README.md
浏览文件 @
40a09696
...
...
@@ -94,7 +94,6 @@
知识图谱里已经沉淀了非常多优质的内容,
**相信能帮助你走的更快、更稳、更远**
。下面 👇🏻 是二哥最近一直在做的三件大事,对你的求职和学习都会很有帮助:
-
✌️:
[
官宣:二哥的Java面试指南+八股文发布了~
](
https://mp.weixin.qq.com/s/3yUT9v3BAdf4rfdfWYbfPw
)
-
✌️:
[
官宣:二哥的实战项目技术派上线了~
](
https://mp.weixin.qq.com/s/B2VOZxj0HnKrO8GFIAggQg
)
-
✌️:
[
官宣:二哥的前端React项目2.0上线了~
](
https://mp.weixin.qq.com/s/MSFOGhBupTgpSSt6UDfRug
)
...
...
@@ -112,7 +111,6 @@
-
[
在macOS和Windows上安装Intellij IDEA
](
docs/overview/IDEA-install-config.md
)
-
[
编写第一个程序Hello World
](
docs/overview/hello-world.md
)
## Java基础语法
-
[
48个关键字及2个保留字全解析
](
docs/basic-extra-meal/48-keywords.md
)
...
...
docs/thread/thread-group-and-thread-priority.md
浏览文件 @
40a09696
---
title
:
线程组
是什么?线程优先级如何设置?
title
:
线程组
和线程优先级
shortTitle
:
线程组和线程优先级
description
:
线程组是什么?线程优先级如何设置?
category
:
...
...
@@ -12,61 +12,54 @@ head:
content
:
Java,并发编程,多线程,Thread,线程组,线程优先级
---
#
线程组是什么?线程优先级如何设置?
#
14.4 线程组和线程优先级
## 线程组(ThreadGroup)
##
#
线程组(ThreadGroup)
Java
中
用ThreadGroup来表示线程组,我们可以使用线程组对线程进行批量控制。
Java用ThreadGroup来表示线程组,我们可以使用线程组对线程进行批量控制。
ThreadGroup和Thread的关系就如同他们的字面意思一样简单粗暴,每个Thread必然存在于一个ThreadGroup中,Thread不能独立于ThreadGroup存在。执行
main()方法线程的
名字是main,如果在new Thread时没有显式指定,那么默认将父线程(当前执行new Thread的线程)线程组设置为自己的线程组。
ThreadGroup和Thread的关系就如同他们的字面意思一样简单粗暴,每个Thread必然存在于一个ThreadGroup中,Thread不能独立于ThreadGroup存在。执行
`main()`
方法的线程
名字是main,如果在new Thread时没有显式指定,那么默认将父线程(当前执行new Thread的线程)线程组设置为自己的线程组。
示例代码:
```
java
public
class
Demo
{
public
static
void
main
(
String
[]
args
)
{
Thread
testThread
=
new
Thread
(()
->
{
System
.
out
.
println
(
"testThread当前线程组名字:"
+
Thread
.
currentThread
().
getThreadGroup
().
getName
());
System
.
out
.
println
(
"testThread线程名字:"
+
Thread
.
currentThread
().
getName
());
});
testThread
.
start
();
System
.
out
.
println
(
"执行main所在线程的线程组名字: "
+
Thread
.
currentThread
().
getThreadGroup
().
getName
());
System
.
out
.
println
(
"执行main方法线程名字:"
+
Thread
.
currentThread
().
getName
());
}
}
Thread
testThread
=
new
Thread
(()
->
{
System
.
out
.
println
(
"testThread当前线程组名字:"
+
Thread
.
currentThread
().
getThreadGroup
().
getName
());
System
.
out
.
println
(
"testThread线程名字:"
+
Thread
.
currentThread
().
getName
());
});
testThread
.
start
();
System
.
out
.
println
(
"执行main所在线程的线程组名字: "
+
Thread
.
currentThread
().
getThreadGroup
().
getName
());
System
.
out
.
println
(
"执行main方法线程名字:"
+
Thread
.
currentThread
().
getName
());
```
输出结果:
```
java
执行main所在线程的线程组名字
:
main
执行main方法线程名字
:
main
testThread当前线程组名字
:
main
testThread线程名字
:
Thread
-
0
执行main方法线程名字
:
main
```
ThreadGroup管理着它下面的Thread,ThreadGroup是一个标准的
**向下引用**
的树状结构,这样设计的原因是
**防止"上级"线程被"下级"线程引用而无法有效地被GC回收**
。
ThreadGroup是一个标准的
**向下引用**
的树状结构,这样设计可以
**防止"上级"线程被"下级"线程引用而无法有效地被GC回收**
。
### 线程的优先级
## 线程的优先级
Java中线程优先级可以指定,范围是1~10。但是并不是所有的操作系统都支持10级优先级的划分(比如有些操作系统只支持3级划分:低,中,高),Java只是给操作系统一个优先级的
**参考值**
,线程最终
**在操作系统的优先级**
是多少还是由操作系统决定。
线程优先级可以指定,范围是1~10。但并不是所有的操作系统都支持10级优先级的划分(比如有些操作系统只支持3级划分:低、中、高),Java只是给操作系统一个优先级的
**参考值**
,线程最终
**在操作系统中的优先级**
还是由操作系统决定。
Java默认的线程优先级为5,线程的执行顺序由调度程序来决定,线程的优先级会在线程被调用之前设定。
通常情况下,高优先级的线程将会比低优先级的线程有
**更高的
几率**
得到执行。我们使用方法
`Thread`
类的
`setPriority()`
实例方法
来设定线程的优先级。
通常情况下,高优先级的线程将会比低优先级的线程有
**更高的
概率**
得到执行。
`Thread`
类的
`setPriority()`
方法可以用
来设定线程的优先级。
```
java
public
class
Demo
{
public
static
void
main
(
String
[]
args
)
{
Thread
a
=
new
Thread
();
System
.
out
.
println
(
"我是默认线程优先级:"
+
a
.
getPriority
());
Thread
b
=
new
Thread
();
b
.
setPriority
(
10
);
System
.
out
.
println
(
"我是设置过的线程优先级:"
+
b
.
getPriority
());
}
}
Thread
a
=
new
Thread
();
System
.
out
.
println
(
"我是默认线程优先级:"
+
a
.
getPriority
());
Thread
b
=
new
Thread
();
b
.
setPriority
(
10
);
System
.
out
.
println
(
"我是设置过的线程优先级:"
+
b
.
getPriority
());
```
输出结果:
...
...
@@ -75,140 +68,140 @@ public class Demo {
我是设置过的线程优先级
:
10
```
既然有1
-10的级别来设定了线程的优先级,这时候可能有些读者会问,那么我是不是可以在业务实现的时候,采用这种方法来指定一些线程执行的先后顺序
?
既然有1
0个级别来设定线程的优先级,那是不是可以在业务实现的时候,采用这种方法来指定线程执行的先后顺序呢
?
对于这个问题,
我们的答案是:
No!
对于这个问题,
答案是:
No!
Java中的优先级
来说不是特别的可靠,
**Java程序中对线程所设置的优先级只是给操作系统一个建议,操作系统不一定会采纳。而真正的调用顺序,是由操作系统的线程调度算法
决定的**
。
Java中的优先级
不是特别的可靠,
**Java程序中对线程所设置的优先级只是给操作系统一个建议,操作系统不一定会采纳。而真正的调用顺序,是由操作系统的线程调度算法来
决定的**
。
我们通过代码来验证一下:
```
java
public
class
Demo
{
public
static
class
T1
extends
Thread
{
@Override
public
void
run
()
{
super
.
run
();
System
.
out
.
println
(
String
.
format
(
"当前执行的线程是:%s,优先级:%d"
,
Thread
.
currentThread
().
getName
(),
Thread
.
currentThread
().
getPriority
()));
}
static
class
MyThread
extends
Thread
{
@Override
public
void
run
()
{
// 输出当前线程的名字和优先级
System
.
out
.
println
(
"MyThread当前线程:"
+
Thread
.
currentThread
().
getName
()
+
",优先级:"
+
Thread
.
currentThread
().
getPriority
());
}
}
public
static
void
main
(
String
[]
args
)
{
IntStream
.
range
(
1
,
10
).
forEach
(
i
->
{
Thread
thread
=
new
Thread
(
new
T1
());
thread
.
setPriority
(
i
);
thread
.
start
();
});
public
static
void
main
(
String
[]
args
)
{
// 创建 10 个线程,从 1-10 运行,优先级从 1-10
for
(
int
i
=
1
;
i
<=
10
;
i
++)
{
Thread
thread
=
new
MyThread
();
thread
.
setName
(
"线程"
+
i
);
thread
.
setPriority
(
i
);
thread
.
start
();
}
}
```
某次输出:
运行该程序,有时候可以按照优先级执行,有时却不行,这是
某次输出:
```
java
当前执行的线程是
:
Thread
-
17
,
优先级
:
9
当前执行的线程是
:
Thread
-
1
,
优先级
:
1
当前执行的线程是
:
Thread
-
13
,
优先级
:
7
当前执行的线程是
:
Thread
-
11
,
优先级
:
6
当前执行的线程是
:
Thread
-
15
,
优先级
:
8
当前执行的线程是
:
Thread
-
7
,
优先级
:
4
当前执行的线程是
:
Thread
-
9
,
优先级
:
5
当前执行的线程是
:
Thread
-
3
,
优先级
:
2
当前执行的线程是
:
Thread
-
5
,
优先级
:
3
MyThread当前线程
:
线程2
,
优先级
:
2
MyThread当前线程
:
线程4
,
优先级
:
4
MyThread当前线程
:
线程3
,
优先级
:
3
MyThread当前线程
:
线程5
,
优先级
:
5
MyThread当前线程
:
线程1
,
优先级
:
1
MyThread当前线程
:
线程6
,
优先级
:
6
MyThread当前线程
:
线程7
,
优先级
:
7
MyThread当前线程
:
线程8
,
优先级
:
8
MyThread当前线程
:
线程9
,
优先级
:
9
MyThread当前线程
:
线程10
,
优先级
:
10
```
Java提供
一个
**线程调度器**
来监视和控制处于
**RUNNABLE状态**
的线程。线程的调度策略采用
**抢占式**
,优先级高的线程比优先级低的线程会有更大的几率优先执行。在优先级相同的情况下,按照“先到先得”的原则。每个Java程序都有一个默认的主线程,就是通过JVM启动的第一个线程main
线程。
Java提供
了一个
**线程调度器**
来监视和控制处于
**RUNNABLE状态**
的
线程。
还有一种线程称为
**守护线程(Daemon)**
,守护线程默认的优先级比较低。
-
线程的调度策略采用
**抢占式**
的方式,优先级高的线程会比优先级低的线程有更大的几率优先执行。
-
在优先级相同的情况下,会按照“先到先得”的原则执行。
-
每个Java程序都有一个默认的主线程,就是通过JVM启动的第一个线程——main线程。
> 如果某线程是守护线程,那如果所有的非守护线程都结束了,这个守护线程也会自动结束。
>
> 应用场景是:当所有非守护线程结束时,结束其余的子线程(守护线程)自动关闭,就免去了还要继续关闭子线程的麻烦。
>
> 一个线程默认是非守护线程,可以通过Thread类的setDaemon(boolean on)来设置。
还有一种特殊的线程,叫做
**守护线程(Daemon)**
,守护线程默认的优先级比较低。
在之前,我们有谈到一个线程必然存在于一个线程组中,那么当线程和线程组的优先级不一致的时候将会怎样呢?我们用下面的案例来验证一下:
-
如果某线程是守护线程,那如果所有的非守护线程都结束了,这个守护线程也会自动结束。
-
当所有的非守护线程结束时,守护线程会自动关闭,这就免去了还要继续关闭子线程的麻烦。
-
线程默认是非守护线程,可以通过Thread类的setDaemon方法来设置为守护线程。
### 线程组和线程优先级之间的关系
之前我们谈到一个线程必然存在于一个线程组中,那么当线程和线程组的优先级不一致的时候会怎样呢?我们来验证一下:
```
java
public
static
void
main
(
String
[]
args
)
{
ThreadGroup
threadGroup
=
new
ThreadGroup
(
"t1"
);
threadGroup
.
setMaxPriority
(
6
);
Thread
thread
=
new
Thread
(
threadGroup
,
"thread"
);
thread
.
setPriority
(
9
);
System
.
out
.
println
(
"我是线程组的优先级"
+
threadGroup
.
getMaxPriority
());
System
.
out
.
println
(
"我是线程的优先级"
+
thread
.
getPriority
());
}
// 创建一个线程组
ThreadGroup
group
=
new
ThreadGroup
(
"testGroup"
);
// 将线程组的优先级指定为 7
group
.
setMaxPriority
(
7
);
// 创建一个线程,将该线程加入到 group 中
Thread
thread
=
new
Thread
(
group
,
"test-thread"
);
// 企图将线程的优先级设定为 10
thread
.
setPriority
(
10
);
// 输出线程组的优先级和线程的优先级
System
.
out
.
println
(
"线程组的优先级是:"
+
group
.
getMaxPriority
());
System
.
out
.
println
(
"线程的优先级是:"
+
thread
.
getPriority
());
```
输出:
> 我是线程组的优先级6
> 我是线程的优先级6
```
线程组的优先级是:7
线程的优先级是:7
```
所以,如果某个线程优先级大于线程所在
**线程组的最大优先级**
,那么该线程的优先级将会失效,取而代之的是线程组的最大优先级。
所以,如果某个线程
的
优先级大于线程所在
**线程组的最大优先级**
,那么该线程的优先级将会失效,取而代之的是线程组的最大优先级。
## 线程组的常用方法及数据结构
##
#
线程组的常用方法及数据结构
### 线程组的常用方法
###
#
线程组的常用方法
**获取当前的线程组名字**
**获取当前
线程
的线程组名字**
~~~
java
```
java
Thread
.
currentThread
().
getThreadGroup
().
getName
()
~~~
```
**复制线程组**
~~~
java
```
java
// 获取当前的线程组
ThreadGroup
threadGroup
=
Thread
.
currentThread
().
getThreadGroup
();
// 复制一个线程组到一个线程数组(获取Thread信息)
Thread
[]
threads
=
new
Thread
[
threadGroup
.
activeCount
()];
threadGroup
.
enumerate
(
threads
);
~~~
```
**线程组统一异常处理**
~~~
java
package
com.func.axc.threadgroup
;
public
class
ThreadGroupDemo
{
public
static
void
main
(
String
[]
args
)
{
ThreadGroup
threadGroup1
=
new
ThreadGroup
(
"group1"
)
{
// 继承ThreadGroup并重新定义以下方法
// 在线程成员抛出unchecked exception
// 会执行此方法
public
void
uncaughtException
(
Thread
t
,
Throwable
e
)
{
System
.
out
.
println
(
t
.
getName
()
+
": "
+
e
.
getMessage
());
}
};
// 这个线程是threadGroup1的一员
Thread
thread1
=
new
Thread
(
threadGroup1
,
new
Runnable
()
{
public
void
run
()
{
// 抛出unchecked异常
throw
new
RuntimeException
(
"测试异常"
);
}
});
thread1
.
start
();
}
}
```
java
// 创建一个线程组,并重新定义异常
ThreadGroup
group
=
new
ThreadGroup
(
"testGroup"
)
{
@Override
public
void
uncaughtException
(
Thread
t
,
Throwable
e
)
{
System
.
out
.
println
(
t
.
getName
()
+
": "
+
e
.
getMessage
());
}
};
~~~
// 测试异常
Thread
thread
=
new
Thread
(
group
,
()
->
{
// 抛出 unchecked 异常
throw
new
RuntimeException
(
"测试异常"
);
});
### 线程组的数据结构
// 启动线程
thread
.
start
();
```
#### 线程组的数据结构
线程组还可以包含其他的线程组,不仅仅是线程。
首先看看
`ThreadGroup`
源码中的成员变量
~~~
java
```
java
public
class
ThreadGroup
implements
Thread
.
UncaughtExceptionHandler
{
private
final
ThreadGroup
parent
;
// 父亲ThreadGroup
String
name
;
// ThreadGroup
r
的名称
int
maxPriority
;
//
线程
最大优先级
String
name
;
// ThreadGroup 的名称
int
maxPriority
;
// 最大优先级
boolean
destroyed
;
// 是否被销毁
boolean
daemon
;
// 是否守护线程
boolean
vmAllowSuspension
;
// 是否可以中断
...
...
@@ -220,29 +213,29 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler {
int
ngroups
;
// 线程组数目
ThreadGroup
groups
[];
// 线程组数组
}
~~~
```
然后看看构造
函数
:
然后看看构造
方法
:
~~~
java
// 私有构造
函数
```
java
// 私有构造
方法
private
ThreadGroup
()
{
this
.
name
=
"system"
;
this
.
maxPriority
=
Thread
.
MAX_PRIORITY
;
this
.
parent
=
null
;
}
// 默认是以当前ThreadGroup
传入作为parent
ThreadGroup,新线程组的父线程组是目前正在运行线程的线程组。
// 默认是以当前ThreadGroup
作为parent
ThreadGroup,新线程组的父线程组是目前正在运行线程的线程组。
public
ThreadGroup
(
String
name
)
{
this
(
Thread
.
currentThread
().
getThreadGroup
(),
name
);
}
// 构造
函数
// 构造
方法
public
ThreadGroup
(
ThreadGroup
parent
,
String
name
)
{
this
(
checkParentAccess
(
parent
),
parent
,
name
);
}
// 私有构造
函数
,主要的构造函数
// 私有构造
方法
,主要的构造函数
private
ThreadGroup
(
Void
unused
,
ThreadGroup
parent
,
String
name
)
{
this
.
name
=
name
;
this
.
maxPriority
=
parent
.
maxPriority
;
...
...
@@ -251,10 +244,11 @@ private ThreadGroup(Void unused, ThreadGroup parent, String name) {
this
.
parent
=
parent
;
parent
.
add
(
this
);
}
~~~
第三个构造函数里调用了
`checkParentAccess`
方法,这里看看这个方法的源码:
```
~~~
java
第三个构造方法里调用了
`checkParentAccess`
方法,来看看这个方法的源码:
```
java
// 检查parent ThreadGroup
private
static
Void
checkParentAccess
(
ThreadGroup
parent
)
{
parent
.
checkAccess
();
...
...
@@ -268,21 +262,17 @@ public final void checkAccess() {
security
.
checkAccess
(
this
);
}
}
~~~
> 这里涉及到`SecurityManager`这个类,它是Java的安全管理器,它允许应用程序在执行一个可能不安全或敏感的操作前确定该操作是什么,以及是否是在允许执行该操作的安全上下文中执行它。应用程序可以允许或不允许该操作。
>
> 比如引入了第三方类库,但是并不能保证它的安全性。
>
> 其实Thread类也有一个checkAccess()方法,不过是用来当前运行的线程是否有权限修改被调用的这个线程实例。(Determines if the currently running thread has permission to modify this thread.)
```
总结来说,线程组是一个树状的结构,每个线程组下面可以有多个线程或者线程组。线程组可以起到统一控制线程的优先级和检查线程的权限的作用
。
这里涉及到
`SecurityManager`
这个类,它是Java的安全管理器,它允许应用程序在执行一个可能不安全或敏感的操作前确定该操作是什么,以及是否是在允许执行该操作的安全上下文中执行它。应用程序可以允许或不允许该操作
。
---
比如引入了第三方类库,但是并不能保证它的安全性。
其实Thread类也有一个checkAccess方法,不过是用来当前运行的线程是否有权限修改被调用的这个线程实例。(Determines if the currently running thread has permission to modify this thread.)
总结一下,线程组是一个树状的结构,每个线程组下面可以有多个线程或者线程组。线程组可以起到统一控制线程的优先级和检查线程权限的作用。
>编辑:沉默王二,内容大部分来源以下三个开源仓库:
>- [深入浅出 Java 多线程](http://concurrent.redspider.group/)
>- [并发编程知识总结](https://github.com/CL0610/Java-concurrency)
>- [Java八股文](https://github.com/CoderLeixiaoshuai/java-eight-part)
编辑:沉默王二,原文内容来源于朋友开源的这个仓库:
[
深入浅出 Java 多线程
](
http://concurrent.redspider.group/
)
,强烈推荐。
----
...
...
docs/thread/thread-state-and-method.md
浏览文件 @
40a09696
...
...
@@ -400,13 +400,7 @@ b 线程状态仍然不固定(RUNNABLE 或 BLOCKED)。
> 在线程中断机制里,当其他线程通知需要被中断的线程后,线程中断的状态被设置为 true,但是具体被要求中断的线程要怎么处理,完全由被中断线程自己而定,可以在合适的实际处理中断请求,也可以完全不处理继续执行下去。
---
> 编辑:沉默王二,内容大部分来源以下三个开源仓库:
>
> - [深入浅出 Java 多线程](http://concurrent.redspider.group/)
> - [并发编程知识总结](https://github.com/CL0610/Java-concurrency)
> - [Java 八股文](https://github.com/CoderLeixiaoshuai/java-eight-part)
编辑:沉默王二,原文内容来源于朋友开源的这个仓库:
[
深入浅出 Java 多线程
](
http://concurrent.redspider.group/
)
,强烈推荐。
---
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录