Thread Suspend

Oil

Grünschnabel
Moin!

Ich habe nach einer Möglichkeit gesucht alle Threads an einer bestimmten Stelle im Code anzuhalten und immer, wenn ein Thread fertig ist den ersten Thread aus der Queue weiterlaufen zu lassen. Ich habe das jetzt in der Art realisiert:

Code:
package de.ausb.dbconnectionmanager.threads;

public class WaitingThread {

	public void suspend() throws InterruptedException {
		synchronized (this) {
			this.wait();
		}
	}

	public void resume() {
		synchronized (this) {
			this.notify();
		}

	}

}
Die Threads erzeugen an einer Stelle ein Objekt von WaitingThread, tragen es in eine ArrayList ein, stoppen mit suspend() und werden dann von einem anderen Thread über resume() wieder gestartet.
Das funktioniert (wider erwarten ;)) auch. Ich denke aber das wird auch eleganter gehen, oder?

PS: Das ist zwar für meine Ausbildung, aber nix für die Produktion, nur zu Spielzwecken. :)
 
Hallo,

Ich habe nach einer Möglichkeit gesucht alle Threads an einer bestimmten Stelle im Code anzuhalten und immer, wenn ein Thread fertig ist den ersten Thread aus der Queue weiterlaufen zu lassen. Ich habe das jetzt in der Art realisiert:
Du musst schon etwas genauer beschreiben was du willst. Wenn doch alle Threads an dieser bestimmten Stelle angehalten haben, wie kann denn dann noch ein
Thread fertig werden? Oder willst du, das ein paar Threads an einer Stelle auf das Eintreten einer Bedingung warten und anschließend einer oder alle wartenden Threads weiterlaufen?

Gruß Tom
 
Du musst schon etwas genauer beschreiben was du willst. Wenn doch alle Threads an dieser bestimmten Stelle angehalten haben, wie kann denn dann noch ein
Thread fertig werden? Oder willst du, das ein paar Threads an einer Stelle auf das Eintreten einer Bedingung warten und anschließend einer oder alle wartenden Threads weiterlaufen?

Ich wollte eine Art Verbindungsmanager-Bibliothek für MySQL Datenbanken basteln, die es ermöglichen soll auch dauerhafte Verbindungen zu benutzen (Ich weiß, so richtig sinnvoll ist das nicht ;)). Jedenfalls kann da eine Anzahl an zu öffnenden Verbindungen mitgegeben werden und so lange noch nicht so viele Connections geöffnet wurden, wie konfiguriert wird bei einer Anfrage immer eine neue geöffnet. Sonst wird überprüft ob eine geschlossen oder vom Programmierer wieder freigegeben wurde.
Wenn aber alle gerade besetzt sind soll sich der Thread so lange schlafen legen bis eine Verbindung wieder freigegeben wurde. Dann soll der freigebende Thread halt immer den ersten Thread aus der Schlange (der am längsten wartet) weiterlaufen lassen.

Code:
package de.ausb.dbconnectionmanager;

..................

import de.ausb.dbconnectionmanager.threads.WaitingThread;

public class ConnectionDOM {

	private String host;

	private String scheme;

	private String user;

	private String password;

	private boolean persistent;

	private int connectionPoolSize;

	//Speicherung der dauerhaften Datenbankverbindungen
	private ArrayList<ConnectionDecorator> connections;

	//wartende Threads (nur für dauerhafte Verbindung -> persistent==true)
	private ArrayList<WaitingThread> waitingThreads;

	public ConnectionDOM(String host, String scheme, String user,
			String password, int connectionPoolSize,  						boolean persistent) {
		setHost(host);
		setScheme(scheme);
		setUser(user);
		setPassword(password);
		setConnectionPoolSize(connectionPoolSize);
		setPersistent(persistent);
	}

	public ConnectionDOM() {
		setConnectionPoolSize(1);
		setPersistent(false);
	}

	private ConnectionDecorator openConnection() throws SQLException {

		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://" + getHost() + "/" + 					getScheme();
			Connection connectionLok = 							DriverManager.getConnection(url,
					getUser(), getPassword());
			if (this.isPersistent()) {
				return new ConnectionDecorator	

					(connectionLok, isPersistent(),
						this);
			} else {
				return new ConnectionDecorator(connectionLok);

			}
		} catch (ClassNotFoundException e) {
			throw new SQLException(e.getMessage());
		}
	}

	public ConnectionDecorator getConnection() throws SQLException {
		if (!isPersistent()) {
			return openConnection();
		} else {
			if (getConnections().size() < getConnectionPoolSize()) {
				ConnectionDecorator con = openConnection();
				getConnections().add(con);
				con.setReleased(false);
				return con;
			} else {
				WaitingThread currThread = new WaitingThread();

				getWaitingThreads().add(currThread);
				while (true) {
					synchronized (this) {
						for (ConnectionDecorator c : getConnections()) {
							if (c.isClosed()) {
								ConnectionDecorator newCD = openConnection();
								newCD.setReleased(false);
								getConnections().add(newCD);
								getConnections().remove(c);
								getWaitingThreads().remove(currThread);
								return newCD;
							} else if (c.isReleased()) {
								c.setReleased(false);
								getWaitingThreads().remove(currThread);
								return c;
							}
						}
					}
					try {
						currThread.suspend();
					} catch (InterruptedException e) {
						return null;
					}
				}
			}

		}
	}

	private String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	private String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	private String getScheme() {
		return scheme;
	}

	public void setScheme(String scheme) {
		this.scheme = scheme;
	}

	private String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public int getConnectionPoolSize() {
		return connectionPoolSize;
	}

	public void setConnectionPoolSize(int connectionPool) {
		this.connectionPoolSize = connectionPool;
	}

	private ArrayList<ConnectionDecorator> getConnections() {
		return connections;
	}

	private void setConnections(ArrayList<ConnectionDecorator> connections) {
		this.connections = connections;
	}

	public boolean isPersistent() {
		return persistent;
	}

	public void setPersistent(boolean persistent) {
		this.persistent = persistent;
		if (persistent) {
			setConnections(new ArrayList<ConnectionDecorator>());
			setWaitingThreads(new ArrayList<WaitingThread>());
		}
	}

	public ArrayList<WaitingThread> getWaitingThreads() {
		return waitingThreads;
	}

	private void setWaitingThreads(ArrayList<WaitingThread> waitingThreads) {
		this.waitingThreads = waitingThreads;
	}
}

Code:
package de.ausb.dbconnectionmanager;

..............

import de.ausb.dbconnectionmanager.threads.WaitingThread;

public class ConnectionDecorator implements Connection {

	private Connection connection;

	//dauerhafte Datenbankverbindung 
	private boolean persistent;

	//Verbindung freigegeben (nur fuer dauerhafte Verbindungen)
	private boolean released;

	private ConnectionDOM dom;

	public ConnectionDecorator(Connection connection) {
		setConnection(connection);
		setReleased(true);
		setPersistent(false);
	}

	public ConnectionDecorator(Connection connection, boolean persistent,
			ConnectionDOM dom) {
		setConnection(connection);
		setReleased(true);
		setPersistent(persistent);
		setDom(dom);
	}

	public void close() throws SQLException {
		if (!isPersistent()) {
			getConnection().close();
		} else {
			setReleased(true);
		}
	}

	private Connection getConnection() {
		return connection;
	}

	private void setConnection(Connection connection) {
		this.connection = connection;
	}

	public boolean isPersistent() {
		return persistent;
	}

	private void setPersistent(boolean persistent) {
		this.persistent = persistent;
	}

	public boolean isReleased() {
		return released;
	}

	public void setReleased(boolean released) {
		//nächsten Thread freigeben
		if (getDom() != null && getDom().isPersistent() && getDom().getWaitingThreads().size() >= 1) {
			WaitingThread nextThread = getDom().getWaitingThreads().get(0);
			if (nextThread != null) {
				nextThread.resume();
			}
		}

		this.released = released;
	}

	private ConnectionDOM getDom() {
		return dom;
	}

	private void setDom(ConnectionDOM dom) {
		this.dom = dom;
	}


	...................................

}

Die Stellen die ich meine sind in ConnectionDOM.getConnection() und ConnectionDecorator.setReleased().

Danke schon mal im Voraus :)
 
Zuletzt bearbeitet:
Zurück