03、Java并发-线程组、守护线程和线程优先级

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