黑马程序员技术交流社区
标题:
关于 synchronized 和 wait 的问题
[打印本页]
作者:
heheka123
时间:
2014-4-20 13:21
标题:
关于 synchronized 和 wait 的问题
本帖最后由 heheka123 于 2014-4-21 19:59 编辑
先看这个段代码,是老师讲生产者消费者的时候的
public synchronized void set(String name){
while(flag){
try{wait();}catch(Exception e){}
}
this.name=name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"....生产者..."+this.name);
flag=true;
this.notifyAll();
}
复制代码
这个方法上有个 synchronized 意思就是 当有第二个线程是进不来的, 那里面的wait() 还有什么用呢,让谁等待啊?
作者:
呆呆沙师妹
时间:
2014-4-20 13:28
区别一下sleep()和wait()。
sleep():让出CUP执行权,不释放同步锁;
wait():不仅让出CUP执行权,并且释放同步锁。
当持有锁的线程进入等待状态,同步锁被释放,别的进程就能进来了。
作者:
清风有意
时间:
2014-4-20 13:29
在方法上的synchronized锁是的对象是本类对象即synchronized(this),这里的生产者和消费者是两个不同的类,所以不是同一个锁,这里加锁是为了同步
作者:
忘川
时间:
2014-4-20 13:34
/*
多线程中最为常见的应用案例:
生产者消费者问题。
生产和消费同时执行,需要多线程。
但是执行的任务却不相同,处理的资源确实相同的:线程间的通信。
1,描述一下资源。
2,描述生产者,因为具备着自己的任务。
3,描述消费者,因为具备着自己的任务。
问题1:数据错误:已经被生产很早期的商品,才被消费到。
出现线程安全问题,加入了同步解决。使用同步函数。
问题已解决:不会在消费到之前很早期的商品。
问题2:发现了连续生产却没有消费,同时对同一个商品进行多次消费。
希望的结果应该是生产一个商品,就被消费掉。生产下一个商品。
搞清楚几个问题?
生产者什么时候生产呢?消费者什么时候应该消费呢?
当盘子中没有面包时,就生产,如果有了面包,就不要生产。
当盘子中已有面包时,就消费,如果没有面包,就不要消费。
生产者生产了商品后应该告诉消费者来消费。这时的生产者应该处于等待状态。
消费者消费了商品后,应该告诉生产者,这时消费者处于等待状态。
等待:wait();
告诉:notify();//唤醒
问题解决:实现生产一个消费一个。
=====================
等待/唤醒机制。
wait(): 会让线程处于等待状态,其实就是将线程临时存储到了线程池中。
notify():会唤醒线程池中任意一个等待的线程。
notifyAll():会唤醒线程池中所有的等待线程。
记住:这些方法必须使用在同步中,因为必须要标识wait,notify等方法所属的锁。
同一个锁上的notify,只能唤醒该锁上的被wait的线程。
为什么这些方法定义在Object类中呢?
因为这些方法必须标识所属的锁,而锁可以是任意对象,任意对象可以调用的方法必然时Object类中的方法。
举例:小朋友抓人游戏。
*/
//1,描述资源。属性:商品名称和编号, 行为:对商品名称赋值,获取商品。
class Resource
{
private String name;
private int count = 1;
//定义标记。
private boolean flag = false;
//1,提供设置的方法。
public synchronized void set(String name)
{
if(flag)
try{this.wait();}catch(InterruptedException e){}
//给成员变量赋值并加上编号。
this.name = name + count;
//编号自增。
count++;
//打印生产了哪个商品。
System.out.println(Thread.currentThread().getName()+"......生产者...."+this.name);
//将标记改为true。
flag = true;
//唤醒消费者。
this.notify();
}
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"....消费者...."+this.name);
//将标记该为false。
flag = false;
//唤醒生产者。
this.notify();
}
}
//2,描述生产者。
class Producer implements Runnable
{
private Resource r ;
// 生产者一初始化就要有资源,需要将资源传递到构造函数中。
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set("面包");
}
}
}
//3,描述消费者。
class Consumer implements Runnable
{
private Resource r ;
// 消费者一初始化就要有资源,需要将资源传递到构造函数中。
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ThreadDemo9
{
public static void main(String[] args)
{
//1,创建资源对象。
Resource r = new Resource();
//2,创建线程任务。
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
//3,创建线程。
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
t1.start();
t2.start();
}
}
复制代码
你没看全啊,这是毕姥爷讲课的笔记,你看下,wait()是让当前这个线程进入等待
作者:
清风夜独醉
时间:
2014-4-20 14:11
首先你要明白wait()方法的作用:
wait()方法,线程会停止运行,不会自动启动,要等其它线程唤醒。然后该线程不但交出CPU执行权,并且还释放锁,也就是说该线程不再持有锁,其它线程可以进来。
另外你要与sleep()方法区别开,别混淆了。
sleep()方法,线程会暂时停止运行,并交出CPU执行权,等睡眠时间到了线程会继续启动,但是这个过程并不释放锁,也就是说该线程仍然持有锁,其它线程进不来。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2