我写了一个java程序来为文件中的每一行生成唯一的id。可能有多个作业运行相同的程序以获得唯一的ID。对于任何文件中的每一行,此id必须是唯一的。我试图通过将值序列化到文件来实现此目的。由于多个作业将使用此程序,因此我使方法同步。代码适用于单个作业,但是当尝试同时运行多个作业时,同步方法失败。当有一个已经运行时,看起来在同一个对象上再次调用方法。为什么synchronized方法没有锁定对象?
下面是我写的id生成代码 -
public class CreateId2 implements Serializable {
private static final long serialVersionUID = 1L;
private long i;
public synchronized long idGenerate() {
long k = this.generateId(this);
return k;
}
private long generateId(CreateId2 id){
long returnedVal = id.getI();
try {
returnedVal = id.readObject();
//System.out.println("previous modiefiied returnedVal is" + returnedVal);
} catch (FileNotFoundException ex) {
id.setI(200L); //start from 200 for the first time
returnedVal=id.getI();
} catch (Exception ex2) {
ex2.printStackTrace();
}
returnedVal = returnedVal +1;
id.setI(returnedVal);
//System.out.println("returnedVal is " + returnedVal);
try {
id.saveObject(id);
} catch (Exception ex3) {
ex3.printStackTrace();
}
return returnedVal;
}
public void saveObject(CreateId2 id) throws IOException{
//System.out.println("saving object " + id.getI());
File savedFileName = new File("C:\\Users\\sam\\Desktop\\tests\\test.ser");
FileOutputStream savedOutput = new FileOutputStream(savedFileName);
ObjectOutputStream oos = new ObjectOutputStream(savedOutput);
oos.writeObject(id);
oos.flush();
// close the writing.
oos.close();
//System.out.println("saved. value is " + id.getI());
}
public long readObject() throws IOException, ClassNotFoundException{
//System.out.println("read object is called. value is " + ci2.getI());
File savedFileName = new File("C:\\Users\\sam\\Desktop\\tests\\test.ser");
FileInputStream savedInput = new FileInputStream(savedFileName);
ObjectInputStream ois = new ObjectInputStream(savedInput);
//long val = Long.parseLong(ois.readObject().toString());
CreateId2 ci2 = (CreateId2) ois.readObject();
//System.out.println("value of valtemp " + ci2.getI());
long val = Long.valueOf(ci2.getI());
ois.close();
return val;
// close the writing.
}
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
//CreateId2.i = i;
}
// setter methods
private static CreateId2 instance = null;
private CreateId2() { }
public static CreateId2 getInstance() {
if (instance == null) {
instance = new CreateId2();
}
return instance;
}
}
我这样称呼这个方法 -
CreateId2 id = CreateId2.getInstance();
long j = id.idGenerate();
当我同时调用此方法时,我得到以下错误。生成的ID也不再是唯一的。
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2325)
at java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(ObjectInputStream.java:2806)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:704)
at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:830)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at helperPackage.CreateId2.readObject(CreateId2.java:66)
at helperPackage.CreateId2.generateId(CreateId2.java:23)
at textFile.RandomTest.main(RandomTest.java:18)
答案 0 :(得分:0)
synchronized
仅适用于同一JVM中同一对象同步的两个类。如果您有多个监视器对象实例,或者在多个JVM中运行,或者在批处理系统下,每个作业都有自己的类加载器,那么synchronized
将无法正常工作。使用type-4 UUID,它是随机的128位值和"保证"独一无二。
(即使你在宇宙时代每秒产生100万UUID,也很难发生碰撞)
答案 1 :(得分:0)
idGenerate()是线程安全的,但是你的单例构造函数不是线程安全的。您可以创建许多 CreateId2 对象。见an example of a thread-safe Singleton