我觉得线程最难的是同步,是吗?
public class ProducerConsumerDemo {
public static void main(String[] args) {
CubbyHole c = new CubbyHole(); //同步问题的产生,是不是正因为共享一个对象?
Producer p1 = new Producer(c,1);
Consumer c1 = new Consumer(c,1);
p1.start();
c1.start();
}
}
class Producer extends Thread{
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c,int number){
cubbyhole = c;
this.number = number;
}
public void run(){
for(int i=0;i<10;i++){
cubbyhole.put(i);
System.out.println("Producer No."+this.number+"put: "+i);
try{
sleep((int)Math.random()*100);
}catch(InterruptedException e){}
}
}
}
class Consumer extends Thread{
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c,int number){
cubbyhole = c;
this.number = number;
}
public void run(){
int value = 0;
for(int i=0;i<10;i++){
value = cubbyhole.get();
System.out.println("Consumber No." + this.number +"got: "+value);
}
}
}
class CubbyHole{
private int contents;
private boolean available = false; //这个变量我觉得可有可无
public synchronized int get(){
while(available == false) {
try{
wait();
}catch(InterruptedException e){}
}
available = false;
notifyAll(); //我觉得与notify一样的。这个去掉也是能正确执行,晕
return contents;
}
public synchronized void put(int value){
while(available == true){
try{
wait();
}catch(InterruptedException e){}
}
contents = value;
available = true;
notify();
}
}
public class ProducerConsumerDemo {
public static void main(String[] args) {
CubbyHole c = new CubbyHole(); //同步问题的产生,是不是正因为共享一个对象?
Producer p1 = new Producer(c,1);
Consumer c1 = new Consumer(c,1);
p1.start();
c1.start();
}
}
class Producer extends Thread{
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c,int number){
cubbyhole = c;
this.number = number;
}
public void run(){
for(int i=0;i<10;i++){
cubbyhole.put(i);
System.out.println("Producer No."+this.number+"put: "+i);
try{
sleep((int)Math.random()*100);
}catch(InterruptedException e){}
}
}
}
class Consumer extends Thread{
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c,int number){
cubbyhole = c;
this.number = number;
}
public void run(){
int value = 0;
for(int i=0;i<10;i++){
value = cubbyhole.get();
System.out.println("Consumber No." + this.number +"got: "+value);
}
}
}
class CubbyHole{
private int contents;
private boolean available = false; //这个变量我觉得可有可无
public synchronized int get(){
while(available == false) {
try{
wait();
}catch(InterruptedException e){}
}
available = false;
notifyAll(); //我觉得与notify一样的。这个去掉也是能正确执行,晕
return contents;
}
public synchronized void put(int value){
while(available == true){
try{
wait();
}catch(InterruptedException e){}
}
contents = value;
available = true;
notify();
}
}
available 代表格子中是否有物品
上来时是false,说明没物品,这样生产者就可以put,但消费者get的话就会wait然后,生产者put之后,把格子标为满格,这样生成者就不能继续put了,然后唤醒所有等待cubbyhole的线程
这时消费者被唤醒,进行消费,然后把格子标空,然后唤醒所有等待cubbyhole的线程,生产者就能继续生产
//我觉得与notify一样的。这个去掉也是能正确执行?
同步问题是因为在整个执行过程中,大家都会不定时的使用到同一个对象里的东西。
使用private boolean available = false; 这个变量,2楼说得挺明白的。
notifyAll() 这个方法则是一定需要的。因为当你是几个线程同时运行的时候,会有可能随机出现仓库满致使生产者无法put而进入wait状态,或者是出现仓库空儿致使消费者听着消费无法get而进入wait状态。此时若没有notifyAll() 则会出现一个永久等待,使得程序无法继续执行。( 然,你可以不使用notifyAll()而使用notify() )
如果没有这个变量,无论是生产者还是消费者在生产数据和取数据时都会发生等待,也就是会导致相互等待的问题,也就是出现死锁了。notifyAll(); //我觉得与notify一样的。这个去掉也是能正确执行,晕 你可以在Consumer的run方法中加个
for(int i=0;i<10;i++){
try{
Thread.sleep(1000);
} catch(Exception e) {}
来看看效果,就会出现不同步的问题了。
public synchronized void put(int value){
while(available == true){
try{
wait();
}catch(InterruptedException e){}
}
contents = value;
available = true;
notify(); //这个notify会不会唤醒同一工程里其它了正在wait的线程,那不是乱套了吗?
}[/java]
代码也可以这么写public void put(int value) {
synchronized (this) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
this.notify();
}
}
等待this,也就是c这个资源notify(); 就是 this.notify()
释放c这个资源
对的。如果每个线程使用独立的CubbyHole ,那就不是多线程了。多线程实际就是说的多个线程同时对一个资源来读写。private boolean available = false; //这个变量我觉得可有可无
这个变量其实就是一个标识位,用来标识生产线程是否可以继续生产,消费线程是否可以继续消费。如果没这个变量的话,就没法判断生产线程什么时候继续生产,消费线程什么时候可以继续消费notifyAll(); //我觉得与notify一样的。这个去掉也是能正确执行,晕
能正确执行是因为线程没有休眠足够长的时间,就像5L的哥们说的那样,你让生产者或者消费者休眠一下。或者让生产者休眠的时间大于消费者休眠的时间 ,或者让生产者休眠的时间小于消费者休眠的时间,这个时候注释notifyAll(); 后,程序就会挂起了。你注释的是get中的notifyAll();。你可以让生产线程生产的速度大于消费线程,也就是让生产者休眠的时间小于消费者休眠的时间。这样生产完成后,生产线程wait()。然后消费线程调用get后,不会notifyAll();。由于生产线程不会被唤醒,迟早会有消费完的一个时点,那个时候之后,两个线程都处于休眠了。程序就会挂起了
notify(); //这个notify会不会唤醒同一工程里其它了正在wait的线程,那不是乱套了吗?
会的,全部唤醒只是说一起去竞争cpu的资源罢了 最终在一个cpu中执行的线程永远就只有一个
但是由于在waitset中如果有多个线程时,还会存在竞争机制,不一定会notify到你要的那个线程,采用notifyAll会让处于wait的所有线程一块重新竞争,这也就是while (available == true)这为什么要用while而不用if的原因了,因为有可能自己的wait的线程是由于被的原因被别的线程notify.