1. 线程组
可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的组织结构有点类似于树的形式,如图所示:
线程组的作用是:可以批量管理线程或线程组对象,有效地对线程或线程组对象进行组织。线程组的activeCount()可以获得活动线程的总数,但由于线程是动态的,因此这个值只是一个估计值,无法确定精确,list()方法可以打印这个线程组中所有的线程信息,对调试有一定帮助。使用Thread的构造函数,指定线程所属的线程组,将线程和线程组关联起来。
线程组还有一个值得注意的方法stop(),它会停止线程组中所有的线程。这看起来是一个很方便的功能,但是它会遇到和Thread.stop()相同的问题,因此使用时也需要格外谨慎。
2. 守护线程
- 在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程就可以理解为守护线程。
- 当一个Java应用内,所有非守护进程都结束时,Java虚拟机就会自然退出。
而Java中变成守护线程就相对简单了。
Thread t=new DaemonT();
t.setDaemon(true);
t.start();
这样就开启了一个守护线程。
package test;
public class Test
{
public static class DaemonThread extends Thread
{
@Override
public void run()
{
for (int i = 0; i < 10000000; i++)
{
System.out.println("hi");
}
}
}
public static void main(String[] args) throws InterruptedException
{
DaemonThread dt = new DaemonThread();
dt.start();
}
}
当线程dt不是一个守护线程时,在运行后,我们能看到控制台输出hi
当在start之前加入
dt.setDaemon(true);
控制台就直接退出了,并没有输出。
3. 线程优先级
Thread类中有3个变量定义了线程优先级。
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
package test;
public class Test
{
public static class High extends Thread
{
static int count = 0;
@Override
public void run()
{
while (true)
{
synchronized (Test.class)
{
count++;
if (count > 10000000)
{
System.out.println("High");
break;
}
}
}
}
}
public static class Low extends Thread
{
static int count = 0;
@Override
public void run()
{
while (true)
{
synchronized (Test.class)
{
count++;
if (count > 10000000)
{
System.out.println("Low");
break;
}
}
}
}
}
public static void main(String[] args) throws InterruptedException
{
High high = new High();
Low low = new Low();
high.setPriority(Thread.MAX_PRIORITY);
low.setPriority(Thread.MIN_PRIORITY);
low.start();
high.start();
}
}
让一个高优先级的线程和低优先级的线程同时争夺一个锁,看看哪个最先完成。
当然并不一定是高优先级一定先完成。再多次运行后发现,高优先级完成的概率比较大,但是低优先级还是有可能先完成的。
4. 基本的线程同步操作
synchronized 和 Object.wait() Obejct.notify()
synchronized有三种加锁方式:
- 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
- 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
- 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。
作用于实例方法,则不要new两个不同的实例
作用于静态方法,只要类一样就可以了,因为加的锁是类.class,可以new两个不同实例。
wait和notify的用法:用什么锁住,就用什么调用wait和notify