2016-06-04 4 views
-1

Я написал программу java для создания уникального идентификатора для каждой строки в файле. Для получения уникальных идентификаторов может быть несколько заданий, выполняющих ту же самую программу. Этот идентификатор должен быть уникальным для каждой строки в любом файле. Я попытался добиться этого путем сериализации значения в файл. Поскольку несколько заданий будут использовать эту программу, я заставил метод синхронизироваться. Код работает отлично для одиночного задания, но при попытке выполнить несколько заданий в то же время синхронизированный метод выходит из строя. Похоже, метод снова вызывается на том же объекте, когда он уже запущен. Почему синхронизированный метод не блокирует объект?Java Synchronized method не является объектом блокировки

Ниже ид генерировать код, который я написал -

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(); 

Когда я называю этот метод одновременно я получаю эту ошибку ниже. Также созданные идентификаторы больше не уникальны.

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

Синхронизация не вызывает 'EOFExceptions'. Чтение прошедшего конца потока вызывает «EOFExceptions». Это работа для базы данных. – EJP

+0

Это правильно. Но я получаю EOFExceptions только тогда, когда я пытаюсь запустить задания параллельно. По какой-то причине я не могу понять, почему это исключение бросается. –

ответ

0

synchronized работает только для двух классов синхронизации на одном объекте в одной и той же виртуальной машины Java. Если у вас несколько экземпляров объекта монитора или запущены в нескольких JVM или в системе пакетной обработки, где каждое задание получает свой собственный загрузчик классов, то не будет работать. Используйте UUID типа 4, которые являются случайными 128-битными значениями и «гарантированы», чтобы быть уникальными.

(Гарантированный в том смысле, что столкновение вряд ли произойдет, даже если вы сгенерировали 1 миллион UUID, в секунду для возраста Вселенной)

+0

Большое спасибо за ваш ответ. Я использую тот же JVM. Я попытался вызвать метод на том же объекте, получив только существующий экземпляр, но я не могу сделать это правильно. Я протестировал его, открыв два окна экземпляра eclipse и выполнив две петли один за другим. Что может быть проблемой здесь? –

+0

@SamH, если вы «открываете 2 затмения ... бла-бла», тогда вы используете 2 отдельных процесса. SO вы используете 2 отдельных JVM. SO не будет синхронизироваться между ними, используя ключевое слово «synchronized». Если вы спросите, почему, ответ короткий: поскольку некоторая переменная, которую вы используете для синхронизации (позволяет называть ее LOCK), является РАЗЛИЧНЫМИ ОБЪЕКТАМИ - контекст среды выполнения не разделяет между этими процессами, так что LOCK1! = LOCK2. – Antoniossss

0

Джим Гаррисон ответил на многие ситуации могут вызывает проблему. Я хочу добавить еще одну возможную (и общую) ошибку, которая может вызвать эту проблему:

idGenerate() является потокобезопасным, но ваш singleton-конструктор не является потокобезопасным. Есть шанс создать много объектов CreateId2. См. an example of a thread-safe Singleton

+0

Я попробовал второй вариант из ссылки (Auto ThreadSafe Singleton Pattern), но все же те же ошибки.Написал это и распространил его на тестовый класс - открытый класс ThreadSafeSingleton { \t закрытый статический окончательный экземпляр CreateId2 = новый CreateId2(); \t \t защищен ThreadSafeSingleton() { \t} \t // инициализация выполнения \t // По DEFUALT THREADSAFE \t общественного статическую GetInstance Object() { \t \t возвратный экземпляр; \t} } –

Смежные вопросы