java多线程之线程状态

转载请注明出处

http://blog.csdn.net/pony_maggie/article/details/42886735


作者:小马


新建状态(New)

新创建了一个线程对象,但是还没有start。

就绪状态(Runnable)
线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。也是通常线程的状态。

运行状态(Running)
就绪状态的线程获取了CPU,执行程序代码。

死亡状态(Dead)
线程执行完了,比如run方法结束。或者因异常退出了run()方法。另外还有一个destroy方法,一般不建议使用。

阻塞状态(Blocked)
阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的原因有以下几种:
1 调用sleep(milliseconds)方法,JVM会把该线程置为阻塞状态,直到指定的时间结束。

2 调用了suspend方法变为阻塞状态,这种只能通过调用resume方法恢复。这种方式已经不用了。

3 运行的线程执行wait()方法, JVM会把该线程放入等待池中直到线程得到notify或者notifyAll的消息。

4 线程等待I/O处理完毕。

5 运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用。


下面就分别对这5种情况给出demo示例。

首先是两个通用的类,一个是Blockable,它是后面所有要创建线程类的基类,它封装了一个文本框的成员,这个文本框显示它的一个整型成员的值。类的定义如下:

class Blockable extends Thread
{
	private Peeker peeker;
	protected JTextField state = new JTextField(30);
	protected int i;
	public Blockable(Container c)
	{
		c.add(state);
		peeker = new Peeker(this, c);
	}
	
	public synchronized int read() {return i;}
	protected synchronized void update()
	{
		state.setText(getClass().getName() + " state:i = " +
				i);
		
	}
	
	public void stopPeeker()
	{
		peeker.terminate();
	}
}

Blockable还有一个监视器成员,Peeker,它也是一个线程类,它的功能是监视Blockable所有线程实例中整型成员的值,类的定义如下:

class Peeker extends Thread
{
	private Blockable b;
	private int session;
	private JTextField status = new JTextField(30);
	private boolean stop = false;
	public Peeker(Blockable b, Container c)
	{
		c.add(status);
		this.b = b;
		start();
	}
	
	public void terminate()
	{
		stop = true;
	}
	public void run()
	{
		while(!stop)
		{
			status.setText(b.getClass().getName()+
					" Peeker " + (++session) +
					"; value = " + b.read());
			
			try 
			{
				sleep(100);
			} catch (InterruptedException e) 
			{
				System.err.println("Interrupted");
			}
		}
	}
}

先看看sleep的方式,示例创建了两个类进行比较,分别为Sleeper1和Sleeper2,这两个类的唯一区别就在于,run函数里,synchronized修饰的位置,

class Sleeper1 extends Blockable
{
	public Sleeper1(Container c) {super(c);}
	public synchronized void run()
	{
		while(true)
		{
			i++;
			update();
			try 
			{
				sleep(1000);
			} catch (InterruptedException e) 
			{
				System.err.println("Interrupted");
			}
		}
		
	}
}

class Sleeper2 extends Blockable
{
	public Sleeper2(Container c) {super(c);}
	public void run()
	{
		while(true)
		{
			change();
			try 
			{
				sleep(1000);
			} catch (InterruptedException e) 
			{
				System.err.println("Interrupted");
			}
		}
	}
	public synchronized void change()
	{
		i++;
		update();
	}
}

先运行看看效果:

java多线程之线程状态_第1张图片


最上面两个框是Sleeper1和它对应的监视器Peeker, 然后是Sleeper2和它的监视器。

先来分析Sleeper1, 程序一启动时,监视器线程就启动了,点击start后,Sleeper1的实例线程也开始运行,并能获得执行的机会, 但是一旦它获得执行机会(执行run),它就拥有了对象的锁并且不会释放(synchronized加到了整个run上,而run里又有个无限循环。),因为Peeker是这个对象的成员,所以就阻塞了。

所以看到程序的运行效果,Peeker的计数器停止了。Sleeper2没有把整个run置为synchronized,所以不影响Peeker的执行。

总结,
两个Sleeper线程都向我们展示了通过Sleep函数让自己进入睡眠状态,从而其它线程有机会获得执行的机会。当然,synchronized可能会影响结果,这个要注意。


你可能感兴趣的:(java,线程,同步,阻塞,sleep)