简单入门java多线程<二>:线程状态和属性

二、java的线程状态

java的Thread类中包含了一个线程状态枚举类:State

一共六种状态:

(1)New-新生:至今尚未启动的线程,new Thread方式创建

(2)Runnable-可运行:正在 Java 虚拟机中执行(不是运行)的线程, 是否在运行取决于系统是否分配时间片给他

(3)Blocked-被阻塞:等待对象锁

(4)Waiting-等待:无限期地等待某个线程条件的线程,关联操作:Object.wait和Thread.join或者是concurrent库中:Lock和Contidion

(5)Timed waiting-计时等待:限期地等待某个线程条件的线程,关联操作:Thread.sleep、Object.wait、Thread.join、Lock.tryLock和Condition.await

(6)Terminated-被终止:已退出的线程,run执行完,或者由一个未捕获异常意外退出

在给定时间点上,一个线程只能处于一种状态。这些状态是虚拟机状态,它们并没有反映所有操作系统线程状态。所以说这是java的线程状态和大学操作系统课本说的不完全一样。


牢记着六个状态,便与学习java线程的各类行为及相应API的关联。

三、线程属性

(1)优先级:setPriority设置等级1-10。yield让出线程。许多书上都说yield只会将线程让给优先级相对高的,可以源码注释是”allow other threads to execute“,并没有优先级要求,测试下:

public class PriorityYeild extends Thread{
	public static void main(String[] args) {
		Thread a = new PriorityYeild("A");
		a.setPriority(6);
		a.start();
		Thread b = new PriorityYeild("B");
		b.setPriority(4);
		b.start();
		/*while(true){
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(a.getState());//sleep时,状态为TIMED_WAITING
		}*/
	}
	@Override
	public  void run(){
		int i=0;
		while(i<20){
			i++;
			System.out.println(Thread.currentThread().getName()+"------------------"+i);
			if(i==10){
				Thread.yield();
				/*try {
					Thread.sleep(10000);//测试睡眠线程的线程状态
				} catch (InterruptedException e) {
					e.printStackTrace();
				}*/
			}
		}
	}
	public PriorityYeild(String name) {
		super(name);
	}
}
结果:多次测试发现,A线程也可能让步给优先级更低的B。yield和优先级无关,之后线程将有谁占有,完全取决于线程调度器。

注:sleep()和yield()的区别:sleep()使当前线程进入Timed waiting状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

(2)守护线程:线程分为:用户线程和守护线程。setDaemon设置是否为守护线程(start前调用),当只剩下守护线程,JVM退出。使用:发送信息,清空垃圾缓存。

public class DaemonThread extends Thread{
	@Override
	public void run(){
		while(true){
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			System.out.println(df.format(System.currentTimeMillis()));//报时
		}
	}
	public static void main(String[] args) {
		DaemonThread dThread = new DaemonThread();
		dThread.setDaemon(true);
		dThread.start();
		Scanner scanner = new Scanner(System.in);
		scanner.next();//等待输入,输入后main主线程退出
		Runtime.getRuntime().addShutdownHook(new Thread(){//JVM退出时执行
			@Override
			public void run(){
				System.out.println("JVM exit...");
			}
		});
	}
}
结果:

2014-11-27 10:52:16
2014-11-27 10:52:19
2014-11-27 10:52:22
2014-11-27 10:52:25
1
JVM exit...

(3)线程组:ThreadGroup可以统一管理的线程集合。默认创建线程属于同一个组。

(4)未捕获异常处理器:实现Thread.UncaughtExceptionHandler接口。其实线程组ThreadGroup就实现了该接口。源码处理逻辑:

public void uncaughtException(Thread t, Throwable e) {
	if (parent != null) {
	    parent.uncaughtException(t, e);//先执行父类
	} else {
            Thread.UncaughtExceptionHandler ueh = 
                Thread.getDefaultUncaughtExceptionHandler();//获取未捕获异常的默认处理器
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
		System.err.print("Exception in thread \""
				 + t.getName() + "\" ");
                e.printStackTrace(System.err);//打印错误异常信息
            }
        }
    }


猜你喜欢

转载自blog.csdn.net/qqchaozai/article/details/41080109