2017-12-22 19 views
0

Ich habe zwei synchronized Methoden, von denen jede von einem anderen Thread ausgeführt wird.Wie vermeidet man die gleichzeitige Ausführung von zwei Methoden?

public synchronized ResultSet dbExecuteQuery(String queryStmt); 

public synchronized void dbExecuteUpdate(String queryStmt); 

Wie kann ich sicherstellen, dass ihre Ausführung nicht "überlappt"?

Eine Lösung, die mir in den Sinn kommt, ist die folgende:

public synchronized ResultSet dbExecute(String queryStmt, boolean isUpdate) { 
if (isUpdate) { 
    dbExecuteUpdate(queryStmt); 
    return null; 
} else 
    return dbExecuteQuery(queryStmt); 
} 

Aber es bedeutet, würde ich den ganzen Code in das gesamte Projekt verwendet ändern. Gibt es einen saubereren Weg, es zu tun?

+2

Ihr erster Schnipsel gerade fein ist (vorausgesetzt, beide Threads verwenden das gleiche Objekt ihre Abfragen auszuführen). Was glaubst du synchronisiert? –

+2

Das heißt, eine relationale Datenbank hat ACID-Transaktionen, um ** gleichzeitige ** Abfragen auf sichere Weise ausführen zu können. Du solltest sie nicht synchronisieren. Und das wird sowieso nicht funktionieren, sobald mehrere Clients auf dieselbe Datenbank abzielen. –

Antwort

2

Sie können eine dedizierte Synchronisationsobjekt hinzufügen:

class YourClass { 
    Object syncObject = new Object(); 
    public ResultSet dbExecuteQuery(String queryStmt) { 
     synchronized(syncObject) { 
      // your code 
     } 
    } 

    public void dbExecuteUpdate(String queryStmt) { 
     synchronized(syncObject) { 
      // other code 
     } 
    } 
} 

Aber es ist wahrscheinlich besser, eine ReentrantLock zu verwenden.

class YourClass { 
    private Lock lock = new ReentrantLock(); 
    public ResultSet dbExecuteQuery(String queryStmt) { 
     lock.lock(); 
     // your code 
     lock.unlock(); 
    } 

    public void dbExecuteUpdate(String queryStmt) { 
     lock.lock(); 
     // other code 
     lock.unlock(); 
    } 
} 

Eigentlich, da man ein Lese- und ein eine Schreib, werden Sie wahrscheinlich ReadWriteLock verwenden möchten.

class YourClass { 
    private ReadWriteLock lock = new ReentrantReadWriteLock(); 
    public ResultSet dbExecuteQuery(String queryStmt) { 
     lock.readLock().lock(); 
     // your code 
     lock.readLock()..unlock(); 
    } 

    public void dbExecuteUpdate(String queryStmt) { 
     lock.writeLock()..lock(); 
     // other code 
     lock.writeLock().unlock(); 
    } 
} 

Auf diese Weise können Sie gleichzeitig lesen mehrere Threads haben:

The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

+0

Danke, aber ich bekomme die Fehlermeldung, dass ich 'ReadWriteLock()' nicht instantiieren kann, weil es abstrakt ist. Vielleicht importiere ich die falsche Bibliothek? – Robb1

+0

Verwenden Sie 'ReentrantReadWriteLock', es ist eine Implementierung der' ReadWriteLock'-Schnittstelle. – user6690200

+1

@ Robb1 müssen Sie lernen, die Javadoc zu verwenden: https://docs.oracle.com/javase/locks/docs/api/java/util/concurrent/locks/ReadWriteLock.html. Es hat am Anfang einen Abschnitt namens "Alle bekannten implementierenden Klassen". Aber nochmal, all das ist nutzlos? Datenbanken unterstützen gleichzeitige Transaktionen. –

Verwandte Themen