本文共 3970 字,大约阅读时间需要 13 分钟。
java thread有五种状态类型
当我们调用线程类的sleep()、suspend()、yield()、wait()
等方法时会导致线程进入阻塞状态。
了解更详细信息可以参考:
首先,sleep()、suspend()、yield ()
等方法都隶属于 Thread 类,但wait()/notify()
这一对却直接隶属于Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized
方法或块中调用,理由也很简单,只有在synchronized
方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized
方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException
异常。
最后,关于 wait() 和 notify() 方法再说明三点:
先写一个计数线程类CountThread:
public class CountThread extends Thread{ int total; @Override public void run(){ synchronized (this){ for(int i=0;i<100;i++){ total=total+1; } this.notify();//唤醒被阻塞的线程 } }}
再写一个测试类作为主线程:
public class TestWait { public static void main(String[] args) { CountThread countThread=new CountThread(); countThread.start(); synchronized (countThread){ System.out.println("等到countThread线程计算结束..."); try { countThread.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("计算的结果是:"+countThread.total); } }}
运行结果:
等到countThread线程计算结束...计算的结果是:100
生产者:
public class Producer extends Thread { public static final int MAX_BOX_SIZE = 5; VectormessageBox = new Vector<>(); @Override public void run() { try { while (true) { putMessage(); } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void putMessage() throws InterruptedException { while (messageBox.size() == MAX_BOX_SIZE) { this.wait();//当箱子满后则进入等待 } messageBox.add(new Date().toString()); System.out.println("放入一条消息"+new Date().toString()); this.notify();//放入消息后唤醒被锁住的线程(取消息线程) } public synchronized void getMessage() throws InterruptedException { while (messageBox.size() == 0) { this.wait();//当箱子空后进入等待 } String message = (String) messageBox.firstElement(); messageBox.removeElement(message); System.out.println("取出一条消息"+message); this.notify();//删除消息后唤醒被锁住的线程(放消息线程) }}
消费者:
public class Consumer extends Thread{ Producer producer; public Consumer(Producer producer){ this.producer=producer; } @Override public void run() { try { while (true) { producer.getMessage(); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { Producer producer=new Producer(); Consumer consumer=new Consumer(producer); producer.start(); consumer.start(); }}
打印结果:
放入一条消息Thu Jul 07 16:44:41 CST 2016放入一条消息Thu Jul 07 16:44:41 CST 2016放入一条消息Thu Jul 07 16:44:41 CST 2016放入一条消息Thu Jul 07 16:44:41 CST 2016放入一条消息Thu Jul 07 16:44:41 CST 2016取出一条消息Thu Jul 07 16:44:41 CST 2016取出一条消息Thu Jul 07 16:44:41 CST 2016取出一条消息Thu Jul 07 16:44:41 CST 2016
转载地址:http://iixpo.baihongyu.com/