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

2 java的线程状态

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

public enum State {
	/**
	 * Thread state for a thread which has not yet started.
	 */
	NEW,

	/**
	 * Thread state for a runnable thread.  A thread in the runnable
	 * state is executing in the Java virtual machine but it may
	 * be waiting for other resources from the operating system
	 * such as processor.
	 */
	RUNNABLE,

	/**
	 * Thread state for a thread blocked waiting for a monitor lock.
	 * A thread in the blocked state is waiting for a monitor lock
	 * to enter a synchronized block/method or
	 * reenter a synchronized block/method after calling
	 * {@link Object#wait() Object.wait}.
	 */
	BLOCKED,

	/**
	 * Thread state for a waiting thread.
	 * A thread is in the waiting state due to calling one of the
	 * following methods:
	 * <ul>
	 *   <li>{@link Object#wait() Object.wait} with no timeout</li>
	 *   <li>{@link #join() Thread.join} with no timeout</li>
	 *   <li>{@link LockSupport#park() LockSupport.park}</li>
	 * </ul>
	 *
	 * <p>A thread in the waiting state is waiting for another thread to
	 * perform a particular action.
	 *
	 * For example, a thread that has called <tt>Object.wait()</tt>
	 * on an object is waiting for another thread to call
	 * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
	 * that object. A thread that has called <tt>Thread.join()</tt>
	 * is waiting for a specified thread to terminate.
	 */
	WAITING,

	/**
	 * Thread state for a waiting thread with a specified waiting time.
	 * A thread is in the timed waiting state due to calling one of
	 * the following methods with a specified positive waiting time:
	 * <ul>
	 *   <li>{@link #sleep Thread.sleep}</li>
	 *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
	 *   <li>{@link #join(long) Thread.join} with timeout</li>
	 *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
	 *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
	 * </ul>
	 */
	TIMED_WAITING,

	/**
	 * Thread state for a terminated thread.
	 * The thread has completed execution.
	 */
	TERMINATED;
}

一共六种状态:

(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的关联。

2.1 关于阻塞与等待的一些思考

Block与Wait都是停止运行,并释放CPU执行权,两者有区别么?

  • Block是基于锁的等待与释放,Wait是基于条件的等待与唤醒
  • Wait条件如果是基于锁对象,那么进去等待状态的同时,会释放锁,即处于Block状态的线程可能恢复运行
  • Block是被迫进入,因为没有获取到锁,而等待则是主动进入,调用wait等方法

3 线程属性

(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);//打印错误异常信息
            }
        }
    }

 

 

 


爱家人,爱生活,爱设计,爱编程,拥抱精彩人生!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qqchaozai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值