Java并发编程(五)线程的管理

线程的管理

当我们在一个系统中使用了非常之多的线程的时候,就非常不方便去管理,于是乎,设计者便设计了一个名为线程组的类,去好好的管理线程。线程组类的名字叫做ThreadGroup

1
2
3
4
5
ThreadGroup tg=new ThreadGroup("printGroup");
//创建线程组
Thread t1=new Thread(tg,"T1");
Thread t2=new Thread(tg,"T2");
//线程加入线程组

我们看看这个thread的构造函数和别的有什么不同吧

1
2
3
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}

可以看到,这里第一个要传入的参数叫ThreadGroup类,第三个叫名字,表示这个线程属于什么什么线程组,什么什么名字。

1
2
3
4
tg.activeCount()
//可以获得活动中的总线程数,但是活动中的线程数只是一个估计值,无法精确
tg.list();
//而list方法则可以打印出所有的线程信息

最后运行一段程序看看

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
public class test implements Runnable{
public static void main(String[] args){
ThreadGroup tg=new ThreadGroup("printGroup");
Thread t1=new Thread(tg,new test(),"T1");
Thread t2=new Thread(tg,new test(),"T2");
t1.start();
t2.start();
System.out.println(tg.activeCount());
tg.list();

}
@Override
public void run() {
String group=Thread.currentThread().getThreadGroup().getName()+"-"+Thread.currentThread().getName();
while (true){
System.out.println("i am "+group);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

2
i am printGroup-T1
i am printGroup-T2
java.lang.ThreadGroup[name=printGroup,maxpri=10]
Thread[T1,5,printGroup]
Thread[T2,5,printGroup]

线程的后台

这里的后台不是指靠山的意思,就是单纯的后台,每个活动都会有后台,很多次要的事物,都是在幕后运行的。比如一家饭馆,等客人就是主场,服务员就是后台,等主场人走光了,后台也就不必继续服务了,这里说线程的后台,就是指的这个意思。有些主线程在不断的消耗资源进行运算,而后台线程则负责资源垃圾的回收,等主线程结束以后,后台线程便会自然结束。

设置后台线程的方法很简单

1
2
3
4
Thread t1= new Thread(new test());
t1.setDaemon(true);
t1.start();
//注意不能够颠倒次序,必须先setdaemon,才能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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class test {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new test1());
Thread t2 = new Thread(new test2());
t1.setDaemon(true);
t2.start();
t1.start();
}
public static class test1 implements Runnable {
@Override
public void run() {
while (true) {//一直在运行
System.out.println("i am alive");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static class test2 implements Runnable {

@Override
public void run() {
try {
Thread.sleep(5000);//等待5秒结束
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

i am alive
i am alive
i am alive
i am alive
i am alive

如上述代码块所示,线程便会在运行后,开始寻找主线程,等待主线程,如果发现没有主线程,或主线程已经结束,只有后台线程才存活,便会结束线程。

线程的优先级

从上面可以看到,线程与线程之间存在着主次关系,那么主线程与主线程之间也有高低之分吗?答案是有的。为了更好的完成线程之间的调度问题,必然有方法也可以控制着线程的优先级,最常用的方式就是主动的去设置线程的优先级setPriority()

1
2
3
4
5
6
7
8
9
10
11
12
13
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}

在这个方法中传入一个数字,代表着线程的优先级,优先级更高的线程便拥有着更高的资源。

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
35
36
37
38
39
40
41
42
43
44
public class test {
public static class high implements Runnable {
static int count=0;
@Override
public void run() {
while (true){
synchronized (test.class){
count++;
if (count>10000){
System.out.println("high is win");
break;
}
}}

}
}
public static class low implements Runnable{
static int count=0;
@Override
public void run() {
while (true){
synchronized (test.class){
count++;
if (count>10000){
System.out.println("low is win");
break;
}
}}

}
}

public static void main(String[] args) {
Thread t1= new Thread(new high());
Thread t2= new Thread(new low());
t1.setPriority(10);//设置优先级
t2.setPriority(1);//设置优先级
t1.start();
t2.start();
}
}

high is win
low is win

但我们常说事无绝对,哪怕是再冰冷的机器也是如此,设置优先级并不代表一定会优先获得,只不过是获得的概率比较大而已,再多试试几次,也会有低优先级的线程先执行完的时候。