站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题wait()h和notify()用法的线程同步问题?

wait()h和notify()用法的线程同步问题?

摘要: wait()h和notify()用法的线程同步问题?


我看这个关于 wait,notify,sleep,join和线程同步问题 的贴子
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx

里边有个例题,模拟了俩个人分别用洗手间的情况,其中:
第一个先刷牙,刷完后,第二个人刷,然后第一个人上厕所,完后再第一个人
就是洗手间(包括厕所功能不能同时用)

我改一下,把洗手间划分为,厕所和洗漱间,一分为二,就是:
第一人刷牙的同时,第二个人上厕所,然后再交换,这里刷牙和上厕所时间是不同的

但是怎么就没有第二个过程,就是第一人上厕所,第2个人刷牙
请各位大侠帮我看看到底怎么回事?非常感谢

━━我修改后代码━━━━━━━━━━━━━━━━━━━━━━━━━━
class Syn
{
public static void main(String[] args) throws Exception
{
TwoPeople.ONE.start();
TwoPeople.TWO.start();
}
}

class TwoPeople extends Thread{
private int i=0;
static Thread ONE=new TwoPeople(1);
static Thread TWO=new TwoPeople(2);

static Object washroom=new Object();
static Object Toilet=new Toilet(); //我加的 厕所 对象
private TwoPeople(int i){this.i=i;}
public void run(){
//头:这是我修改的代码
try{
if(i==1){
synchronized(washroom){
brush();
ONE.wait();
TWO.notify();
release();
}
}else {synchronized(toilet){
release();
TWO.wait();
ONE.notify();
brush();
}
}}catch(Exception e){}
//尾:这是我修改的代码

private void brush() {
System.out.println(-#34;People -#34;+i+-#34; is brushing !-#34;);
try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
//延迟两秒看效果
System.out.println(-#34;People -#34;+i+-#34; has burshed !-#34;);
}
private void release(){
System.out.println(-#34;People -#34;+i+-#34; is releasing !-#34;);
try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
//延迟两秒看效果
System.out.println(-#34;People -#34;+i+-#34; has released !-#34;);
}
}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━以下是原帖中的run方法━━━━━━━━━━━━━━━
/*
synchronized(washroom){
try{
if(i==1){
brush(); //1
washroom.wait(); //2
release(); //6
washroom.notify(); //7
}
else{
brush(); //3
washroom.notify(); //4
washroom.wait(); //5
release(); //8
}
}catch(InterruptedException e){e.printStackTrace();}
}
}*/



顶上去,高手看看


等会有空帮你看看,mark一下


谢谢大侠!这个问题郁闷我二天了!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
代码不用全看,关键的就是run方法里的内容

我想实现的就是,
俩个人俩个线程,一个人刷牙,另个一个人同时上厕所,
牙刷完的人等上厕所,第二个人上完,第一个人就上,同时,第二个人开始刷牙
(当然刷牙所时间可能比上厕所时间长,反正就是谁先结束就先进入等待状态)

听起来很简单,可是实现起来怎么那么困难呢?我昨天睡觉都在想,郁闷到吐血了

我用整理以下我的run方法,思路应该很清晰吧
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if(i==1){
synchronized(washroom) {
try{
brush();
washroom.wait();
toilet.notify();
release();
}catch(InterruptedException e){e.printStackTrace();}
}

}else {
synchronized(toilet){
try{
release();
toilet.wait();
washroom.notify();
brush();
}catch(Exception e){e.printStackTrace();}
}


可以运行的代码。比较一下就可以得出答案。


class Syn
{
public static void main(String[] args) throws Exception
{
TwoPeople.ONE.start();
TwoPeople.TWO.start();
}
}

class TwoPeople extends Thread
{
private int i = 0;
static Thread ONE = new TwoPeople(1);
static Thread TWO = new TwoPeople(2);

static Object washroom = new Object();
static Object toilet = new Object();

private TwoPeople(int i)
{
this.i = i;
}

public void run()
{
try
{
if (i == 1)
{
brush();
release();
}
else
{
release();
brush();
}

}
catch (Exception e)
{
e.printStackTrace();
}
}

private void brush()
{
synchronized (washroom)
{
System.out.println(-#34;People -#34; + i + -#34; is brushing !-#34;);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

System.out.println(-#34;People -#34; + i + -#34; has burshed !-#34;);

washroom.notify();
}
}

private void release()
{
synchronized (toilet)
{
System.out.println(-#34;People -#34; + i + -#34; is releasing !-#34;);
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(-#34;People -#34; + i + -#34; has released !-#34;);

toilet.notify();
}
}
}


其实不用显式地notify(),系统在synchronized语句块之后会自动调用。


up


class CSDN13 {
public static void main(String[] args) throws Exception {
TwoPeople.ONE.start();
TwoPeople.TWO.start();
}
}

class Toilet {

}

class TwoPeople extends Thread {
private int i = 0;

static Thread ONE = new TwoPeople(1);

static Thread TWO = new TwoPeople(2);

static Object washroom = new Object();

static Object toilet = new Toilet(); // 我加的 厕所 对象

private TwoPeople(int i) {
this.i = i;
}

public void run() {
// 头:这是我修改的代码
try {
if (i == 1) {
synchronized (washroom) { //如果没人刷牙,就开始使用washroom
brush();//刷牙
washroom.notify();//刷完牙让位,通知其它等待刷牙的人用
//TWO.notify();

}
synchronized (toilet) {//等待la-#39;shi
release(); //lashi
toilet.notify(); //拉完了,通知其它人拉
}
}
else {
synchronized (toilet) { //如果没人拉,就开始拉,如果有人,等待
release();//开始……
toilet.notify(); //完了,好爽,通知其它等待的人

}
synchronized (washroom) { //如果没人刷牙,就开始使用washroom,如果有人就等待
brush();
washroom.notify();//刷完牙让位,通知其它等待刷牙的人用

}
}
} catch (Exception e) {
}
}

// 尾:这是我修改的代码

private void brush() {
System.out.println(-#34;People -#34; + i + -#34; is brushing !-#34;);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 延迟两秒看效果
System.out.println(-#34;People -#34; + i + -#34; has burshed !-#34;);
}

private void release() {
System.out.println(-#34;People -#34; + i + -#34; is releasing !-#34;);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 延迟两秒看效果
System.out.println(-#34;People -#34; + i + -#34; has released !-#34;);
}
}


if(i==1){
synchronized(washroom){
brush();
ONE.wait();
TWO.notify();
release();
}
}else {synchronized(toilet){
release();
TWO.wait();
ONE.notify();
brush();
}

楼主这部分代码有问题,主要是理解上的错误。既然对toilet对象上锁,就不用ONE,TWO来唤醒和释放


额写个N个人排队上厕所,刷牙滴!
呵呵
package com.ttdev.tcpmonitor;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class Syn
{
public static void main(String[] args) throws Exception
{
WashRoom room = new WashRoom();
Toilet toilet = new Toilet();
People p1 = new People(room,toilet);
People p2 = new People(room,toilet);
People p3 = new People(room,toilet);
p1.start();
p2.start();
p3.start();
}
}

class People extends Thread{
private List locationList = new ArrayList();
private List queue = new ArrayList();
public void addLocation(Object location)
{
if(!locationList.contains(location))
{
locationList.add(location);
}
}

public People(WashRoom room,Toilet toilet)
{
locationList.add(room);
locationList.add(toilet);
}
private Location nextLocation()
{
int size = queue.size();
if(size == 0)
{
//重走!
queue = new ArrayList();
queue.addAll(locationList);
size = queue.size();
}
Random r = new Random();

int index = r.nextInt(size);
Location location = (Location)queue.get(index);
queue.remove(index);//
return location;

}

public void run()
{
while(true)
{
Location location = nextLocation();
synchronized(location)
{
location.toDo();
location.release();
}
}
}


}

abstract class Location
{
protected boolean inUse;
public void toDo(){};
void release(){};
}

class Toilet extends Location
{

public synchronized void toDo()
{
while(inUse)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+-#34; is in the toilet! -#34;);

}
public synchronized void release()
{
inUse =false;
System.out.println(Thread.currentThread().getName()+-#34; release the Toilet !-#34;);
notifyAll();
}
}
class WashRoom extends Location
{
public synchronized void toDo()
{
while(inUse)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+-#34; is in the WashRoom! -#34;);


}
public synchronized void release()
{
inUse =false;
System.out.println(Thread.currentThread().getName()+-#34; release the WashRoom -#34;);
notifyAll();
}
}



对不起:
System.out.println(Thread.currentThread().getName()+-#34; is in the WashRoom! -#34;);之前要加一行:inUse=true;
还有System.out.println(Thread.currentThread().getName()+-#34; is in the toilet! -#34;);之前要加一行:inUse=true;



小弟看了半天可算有个大概的理解了。
Rayuu 的代码,没有用到wait方法,简单好多,以无刀胜有刀!强!
‘其实不用显式地notify(),系统在synchronized语句块之后会自动调用。’
这句话蛮有用的,注释掉notify,结果都一样哈。
fishyqd 代码通俗易懂,还加了注释,谢谢了
我原来可能就是要这个效果吧,我水平差,一直没写成。
Octer 一看就是世外高人呀!我俩个人都弄得焦头烂额的
代码有些地方我还得好好理解,arraylist这个类我不太熟悉

原理我这样理解的:
人是个类,要去的地方是写个对象(洗漱和厕所),
要去的地方有个顺序,先去厕所还是先去洗漱,是这个意思吧?
随机生成的,这个地方,没太看明白
然后运行了,要去的地方加个锁,动作也加了个锁吧?
判断,在不在用?执行动作
最后释放锁
循环是在重走那加的吧?
运行了一下,发现,初始状态是有人已经上厕所中……
有发现,有时某人重复上厕所好多次,拉肚子了吧

代码我还得理解一下

再次感谢所有热心的大侠们!谢谢

ps.分数怎么给,小弟分不多,平分不了哇
编写一个代码,随机一下三个数和为20 的,然后依次给吧
我这个代码太不优化了,丢人呀

结果:
677
━━随机分数代码━━━━━━━━━━━━━━━━━━━━━━━━
//随机6-8之间的三个数,使其和为20
import java.util.Random;
public class Syn{
public static void main (String[] args){
Random r = new Random();
int x,y;
while (true){
x=r.nextInt(8);
y=r.nextInt(8);
if (x-#60;6 -#38;-#38; y-#60;6){
x=r.nextInt(8);
y=r.nextInt(8);
//System.out.println (x+-#34;/t-#34;+y);
}else if ( ((20-x-y)-#62;=6) -#38;-#38; ((20-x-y)-#60;=8) ){
System.out.println (x+-#34; -#34;+y+-#34; -#34;+(20-x-y));
break;
}
}
}
}



呵呵,其实同步会降低代码的运行效率的,通过 notity wait 或者notifyAll 做到间通信,而同步则依赖于同步监试器,当有线程进入该同步代码块或者同步方法,其他线程就无法进入该对象的同步方法。wait是在不满足某些条件下,线程处于阻塞状态,等待notify或者notifyAll去唤醒
如果代码改成这样:
package com.ttdev.tcpmonitor;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class Syn
{
public static void main(String[] args) throws Exception
{
WashRoom room = new WashRoom();
Toilet toilet = new Toilet();
People p1 = new People(room,toilet);
People p2 = new People(room,toilet);
People p3 = new People(room,toilet);
p1.start();
p2.start();
p3.start();
}
}

class People extends Thread{
private List locationList = new ArrayList();
private List queue = new ArrayList();
public synchronized void addLocation(Object location)
{
if(!locationList.contains(location))
{
locationList.add(location);
}
}
public People(WashRoom room,Toilet toilet)
{
addLocation(room);
addLocation(toilet);
}
private Location nextLocation()
{
int size = queue.size();
if(size == 0)
{
//拉肚子了,同时该人有洁癖,继续上厕所,洗漱!
queue = new ArrayList();
queue.addAll(locationList);
size = queue.size();
}
Location location = (Location)queue.get(0);
queue.remove(0);
return location;

}

public void run()
{
while(true)
{
Location location = nextLocation();
//synchronized(location) // discard this line for testing the multi-threads communication
{
location.toDo();
//location.release();
}
}
}


}
abstract class Location
{
protected boolean inUse;
public void toDo(){};
void release(){};
}

class Toilet extends Location
{

public synchronized void toDo()
{
while(inUse)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
inUse =true;
System.out.println(Thread.currentThread().getName()+-#34; is in the toilet! -#34;);
release();

}
public void release()
{
inUse =false;
System.out.println(Thread.currentThread().getName()+-#34; release the Toilet !-#34;);
notifyAll();
}
public String toString()
{
return -#34;Toilet:-#34;+this.hashCode();
}
}
class WashRoom extends Location
{
public synchronized void toDo()
{
while(inUse)
{
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
inUse =true;
System.out.println(Thread.currentThread().getName()+-#34; is in the WashRoom! -#34;);
release();
}
public synchronized void release()
{
inUse =false;
System.out.println(Thread.currentThread().getName()+-#34; release the WashRoom -#34;);
notifyAll();
}
public String toString()
{
return -#34;WashRoom:-#34;+this.hashCode();
}
}



↑返回目录
前一篇: 一个我一直想不通的YY问题,并且强烈希望sun公司倒闭
后一篇: 想利用MVC模式实现一个小程序,遇到了麻烦,高手帮忙看下。在线等