生产者与消费者问题,篮子为SyncStack,物品为Woto(窝头),现在问题是,多个生产者生产,Woto有个静态属性id,每生产一个,id+1,但程序在运行时,(多次试验),有时候第一个记录id不是1,而是被多个线程修改了之后的值,
请问如果保证这个id值线程同步,该问题是在看马士兵老师的javase视频的时候遇到的,我修改了原来的没有同步方法的id产生方法,代码如下,package thread;import java.util.ArrayList;
import java.util.List;public class ProducerAndCustomer { /**
 * @param args
 */
public static void main(String[] args) {
SyncStack stack = new SyncStack();
Producer pc = new Producer(stack);
Customer cs = new Customer(stack);

new Thread(pc).start();
new Thread(pc).start();
new Thread(pc).start();
new Thread(cs).start();
}}class SyncStack {
List<Woto> list = new ArrayList<Woto>();
public static final int capacity = 3;

// 大于或等于 容量则等待
synchronized void push(Woto wt) {
while (list.size()>capacity) {
try {
this.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("生产了wotou" + wt);
list.add(wt);
this.notify();
} public synchronized Woto pop() {
while (list.isEmpty()) {
try {
this.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}


//取得最后放入的窝头
Woto wt = list.remove(list.size()-1);
System.out.println("取了wotou" + wt);
this.notify();
return wt;
}
}class Woto {
public static int id = 0;

public Woto() {
synchronized (this.getClass()) {
idAdd();
}

}

private  synchronized void idAdd() {
id++;
}

// public static synchronized Woto getWoto() {
// return new Woto();
// }

public String toString() {
return "第" + id + "个窝头";
}
}class Producer implements Runnable{
SyncStack stack;

public Producer(SyncStack stack) {
this.stack = stack;
} @Override
public void run() {
for (int i=0; i<SyncStack.capacity; i++) {
Woto wt = new Woto();
stack.push(wt);


try {
Thread.sleep((int)Math.random()*200);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}class Customer implements Runnable {
SyncStack stack;

public Customer(SyncStack stack) {
this.stack = stack;
}

@Override
public void run() {
for (int i=0; i<SyncStack.capacity; i++) {
Woto wt = stack.pop();



try {
Thread.sleep((int)Math.random()*200);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}

解决方案 »

  1.   

    使用volatile修饰的AtomicInteger对象不就好了
      

  2.   

    其实你的Woto类的synchronized方法,在你这个案例里是起不到同步作用的。

    class Woto {
        public static int id = 0;
        
        public Woto() {
            synchronized (this.getClass()) {
                idAdd();
            }
            
        }
        
        private  synchronized void idAdd() {
            id++;
        }
        
    //    public static synchronized Woto getWoto() {
    //        return new Woto();
    //    }
        
        public String toString() {
            return "第" + id + "个窝头";
        }
    }
    改为
    class Woto {
        public static AtomicInteger id = new AtomicInteger(0);
        
        public Woto() {
            idAdd();
        }
        
        private void idAdd() {
            id.incrementAndGet();
        }
        
        public String toString() {
            return "第" + id.get() + "个窝头";
        }
    }
      

  3.   

    id的设计上存在严重不合理,建议修改为:class Woto {
        private static volatile int id = 0; // 私有化,保护起来,不能被随意访问
            
        public static synchronized int getNewId() { // 得到新的id ,应该用static,跟变量一致。
            return ++id;
        }
    }
      

  4.   

    我想了想,应该设一个静态sid和一个普通id; sid是每创建一个新对象就+,然后赋值给id,但是尽管这样,再改为你的代码模式,还是不行啊,我测试的是还是有顺序问题,请问这位大哥和楼下的大哥有什么办法吗?
      

  5.   

    保存的时候,把数据库中最大的id+1当作新的id保存不行吗