昨天讲到了如何实现多线程以及多线程的好处,今天我们来看看线程的睡眠sleep(),多线程问题,sleep()是一个静态方法,以毫秒为为单位,我们为什么要使用睡眠呢?那当然是为了我们宝贵的CPU资源能在短时间内为更多的线程服务,而不是在某段时间内一直被某个线程占用。比如某线程在等待一个资源,这个时候我们通常让此线程先阻塞一会,一段时间后继续进入可运行状态,此时如果线程获得了所需的资源则可以继续运行,否则再阻塞,等待资源降临。

    通过阻塞我们可以大大的提高CPU的利用率。下面我们来看一个使用sleep()方法的例子

 

package com.suda.thread;

public class Mythread5 implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(1000);
				System.out.println(Thread.currentThread().getName() + ",第"
						+ (i + 1) + "次使用");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Mythread5 mt = new Mythread5();
		Thread thread = new Thread(mt);
		thread.start();

	}

}

 运行上面的代码我们可以看见控制台每隔一秒钟打印出一句话。

 

在进行线程编程时难免涉及到多线程的问题,那么当多个线程访问一个资源时,就会出现竞争,举个低俗而实际的例子:N多人要上厕所,而厕所只有一个,这时就造成了竞争,如果厕所没有门,那么所有的人都可以进,这样必定造成混乱,影响正常的如厕秩序。我们如何解决呢?就是给厕所加个门。进去一个人就锁起来,别人必须等你解决了才能进去。而在多线程中为了解决这个问题引入了同步加锁方法,使用synchronized来个操作或者方法加锁。下面我们就已售票的例子来看看加锁的必要性:

 

package com.suda.thread;

public class Mythread_synchronized implements Runnable {
	private int ticket = 5;

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			if (ticket > 0) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + ",正在卖出第"
						+ (this.ticket--) + "张票!");

			}
		}

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Mythread_synchronized mt = new Mythread_synchronized();
		new Thread(mt, "售票员A").start();
		new Thread(mt, "售票员B").start();
		new Thread(mt, "售票员C").start();
	}

}运行结果:
售票员B,正在卖出第5张票!
售票员A,正在卖出第5张票!
售票员C,正在卖出第4张票!
售票员C,正在卖出第3张票!
售票员B,正在卖出第2张票!
售票员A,正在卖出第3张票!
售票员A,正在卖出第1张票!
售票员C,正在卖出第0张票!
售票员B,正在卖出第-1张票!

完全乱了,这就是没加锁的缺陷,十分明显,那我们看看加锁后的方法:

 

package com.suda.thread;

public class Mythread_synchronized implements Runnable {
	private int ticket = 5;

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			synchronized (this) {
				if (ticket > 0) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()
							+ ",正在卖出第" + (this.ticket--) + "张票!");

				}
			}
		}

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Mythread_synchronized mt = new Mythread_synchronized();
		new Thread(mt, "售票员A").start();
		new Thread(mt, "售票员B").start();
		new Thread(mt, "售票员C").start();
	}

}运行结果:
售票员A,正在卖出第5张票!
售票员A,正在卖出第4张票!
售票员A,正在卖出第3张票!
售票员C,正在卖出第2张票!
售票员C,正在卖出第1张票!

  这样就达到了我们正常的结果了。这就是加锁操作,好了,今天先到这儿了,改天继续!