java 多线程等待_Java多线程编程#线程等待机制

1、最佳的模型是:生产者-消费者package com.boonya.multithread.explain;

/** ==============================================

* 文件:ProducerAndConsumer.java

* 描述:生产者--消费者 [生产者生产了之后消费者才能消费]

* 注:引入了等待通知(wait/notify)机制如下:

1、在生产者没有生产之前,通知消费者等待;在生产者生产之后,马上通知消费者消费。

2、在消费者消费了之后,通知生产者已经消费完,需要生产。

* ============================================

*/

public class ProducerAndConsumer {

public static void main(String argv[]){

ShareData s = new ShareData();

new Consumer(s).start();

new Producer(s).start();

}

}

class ShareData{

private char c;

// 通知变量

private boolean writeable = true;

// -------------------------------------------------------------------------

// 需要注意的是:在调用wait()方法时,需要把它放到一个同步段里,否则将会出现

// "java.lang.IllegalMonitorStateException: current thread not owner"的异常。

// -------------------------------------------------------------------------

public synchronized void setShareChar(char c){

if (!writeable){

try{

// 未消费等待

wait();

}catch(InterruptedException e){}

}

this.c = c;

// 标记已经生产

writeable = false;

// 通知消费者已经生产,可以消费

notify();

}

public synchronized char getShareChar(){

if (writeable){

try{

// 未生产等待

wait();

}catch(InterruptedException e){}

}

// 标记已经消费

writeable = true;

// 通知需要生产

notify();

return this.c;

}

}

// 生产者线程

class Producer extends Thread{

private ShareData s;

Producer(ShareData s){

this.s = s;

}

public void run(){

for (char ch = 'A'; ch <= 'Z'; ch++){

try{

Thread.sleep((int)Math.random() * 400);

}catch(InterruptedException e){}

// 生产

s.setShareChar(ch);

System.out.println(ch + " producer by producer.");

}

}

}

// 消费者线程

class Consumer extends Thread{

private ShareData s;

Consumer(ShareData s){

this.s = s;

}

public void run(){

char ch;

do{

try{

Thread.sleep((int)Math.random() * 400);

}catch(InterruptedException e){}

// 消费

ch = s.getShareChar();

System.out.println(ch + " consumer by consumer.");

}while(ch != 'Z');

}

}

2、等待程序结束

package com.boonya.multithread.explain;

/**===================================

* 文件:LetOneThreadSleepAfterAnotherReady.java

* 描述:等待一个线程的结束的两种方法

* ====================================

*/

public class LetOneThreadSleepAfterAnotherReady {

class MyTaskThread extends Thread{

public MyTaskThread(){}

@Override

public void run() {

for (int count = 1,row = 1; row < 20; row++,count++)

{

for (int i = 0; i < count; i++)

{

System.out.print('*');

}

System.out.println();

}

}

}

// 第一种方法:不断查询第一个线程是否已经终止,如果没有,则让主线程睡眠一直到它终止为止

// 即:while/isAlive/sleep

public void Method1(){

MyTaskThread th1 = new MyTaskThread();

MyTaskThread th2 = new MyTaskThread();

// 执行第一个线程

th1.start();

// 不断查询第一个线程的状态

while(th1.isAlive()){

try{

Thread.sleep(100);

}catch(InterruptedException e){

}

}

//第一个线程终止,运行第二个线程

th2.start();

}

// 第二种方法:join()

public void Method2(){

MyTaskThread th1 = new MyTaskThread();

MyTaskThread th2 = new MyTaskThread();

// 执行第一个线程

th1.start();

try{

th1.join();

}catch(InterruptedException e){

}

// 执行第二个线程

th2.start();

}

public static void main(String[] args) {

LetOneThreadSleepAfterAnotherReady mythread=new LetOneThreadSleepAfterAnotherReady();

// mythread.Method1();

mythread.Method2();

}

}

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2013-02-16 15:37

浏览 861

评论

3 楼

boonya

2013-02-18

zjuttsw 写道

zjuttsw 写道

提一点意见:

Object的wait方法(包括它的重载方法),应该始终包含在循环中。否则会造成数据不一致现象。原因是当线程调用wait方法时进入等待队列,当被其它线程唤醒时(notify or notifyAll),它会执行wait语句后面的指令。而不会再判断条件是否满足。

因此应该这样写:

public synchronized void setShareChar(char c){

while (!writeable){          /* 把 if 改成 while */

try{

// 未消费等待

wait();

}catch(InterruptedException e){}

}

同理getShareChar方法也应该把if改成while。

同时因为wait和notify的使用比较困难,容易出错。因此在JDK 1.5版本以后,不建议再使用notify和wait方法。一个更好的方法是使用Java大师(Doug Lea)编写的java.util.concurrent并行包里的API来实现。

谢谢指点!

2 楼

zjuttsw

2013-02-17

zjuttsw 写道

提一点意见:

Object的wait方法(包括它的重载方法),应该始终包含在循环中。否则会造成数据不一致现象。原因是当线程调用wait方法时进入等待队列,当被其它线程唤醒时(notify or notifyAll),它会执行wait语句后面的指令。而不会再判断条件是否满足。

因此应该这样写:

public synchronized void setShareChar(char c){

while (!writeable){          /* 把 if 改成 while */

try{

// 未消费等待

wait();

}catch(InterruptedException e){}

}

同理getShareChar方法也应该把if改成while。

同时因为wait和notify的使用比较困难,容易出错。因此在JDK 1.5版本以后,不建议再使用notify和wait方法。一个更好的方法是使用Java大师(Doug Lea)编写的java.util.concurrent并行包里的API来实现。

1 楼

zjuttsw

2013-02-17

提一点意见:

Object的wait方法(包括它的重载方法),应该始终包含在循环中。否则会造成数据不一致现象。原因是当线程调用wait方法时进入等待队列,当被其它线程唤醒时(notify or notifyAll),它会执行wait语句后面的指令。而不会再判断条件是否满足。

因此应该这样写:

public synchronized void setShareChar(char c){

while (!writeable){          /* 把 if 改成 while */

try{

// 未消费等待

wait();

}catch(InterruptedException e){}

}

同理getShareChar方法也应该把if改成while。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值