Disponibilizando ConcurrencyLock

Ola galera, sou novo por aqui.

Estou disponibilizando este meu trabalho, se trata de uma trava como o sync e entre outros nativos. O que diferencia dos outros é que este pode ser utilizado com Prioridades. Pra quem trabalha com Multi-Threading, isso é uma mão na massa.

Segue o código:

[code]import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**

  • Concurrency Lock
  •     Copyright 2014 Pedro H. Chaves
    
  •     Licensed under the Apache License, Version 2.0 (the "License"); you
    
  •     may not use this file except in compliance with the License. You may
    
  •     obtain a copy of the License at
    
  •     http://www.apache.org/licenses/LICENSE-2.0
    
  •     Unless required by applicable law or agreed to in writing, software
    
  •     distributed under the License is distributed on an "AS IS" BASIS,
    
  •     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    
  •     implied. See the License for the specific language governing
    
  •     permissions and limitations under the License.
    

*/
final public class ConcurrencyLock {

// Final Private Variables
final private AtomicBoolean mAwait = new AtomicBoolean(false);
final private List<Identify> mIdentifications = new ArrayList<Identify>();

// Private Variables
private int mLockCount;
private volatile Thread mIdentify = Thread.currentThread();
private volatile boolean mIdenityLocked = false;
private volatile boolean mInterruptible = true;

/**
 * Set Interruptible
 * 
 * @param interruptible
 */
final public void setInterruptible(final boolean interruptible) {
	mInterruptible = interruptible;
}

/**
 * Try Acquire Lock
 * <p>
 * 
 * @param priority
 *            Greater than 0
 * @param dellayInMillis
 *            Dellay in Millis
 * @return True if was successfully acquired
 */
final public boolean tryAcquire(final int priority, final int dellayInMillis) {
	identify(priority);
	int result = performAcquire(dellayInMillis);
	disidentify();
	if (result > 0)
		acquirePerformed();
	return result == 2;
}

/**
 * Try Acquire Lock
 * <p>
 * 
 * @param priority
 *            Greater than 0
 * @return True if was successfully acquired
 */
final public boolean tryAcquire(final int priority) {
	return tryAcquire(priority, -1);
}

/**
 * Try Acquire Lock
 * <p>
 * 
 * @return True if was successfully acquired
 */
final public boolean tryAcquire() {
	return tryAcquire(0);
}

/**
 * Increments acquire
 */
final public void acquire() {
	if (Thread.currentThread() != mIdentify)
		throw new RuntimeException("Was not possible to acquire another lock because it was not previously locked.");
	mLockCount++;
}

/**
 * Release Lock
 */
final public void release() {
	if (mIdentify != Thread.currentThread()) {
		throw new RuntimeException("Unable to release the lock, because it was not previously captured.");
	} else {
		if (--mLockCount == 0)
			mIdenityLocked = false;
	}
}

/**
 * Return true if was interrupted
 * 
 * @return
 */
final private boolean isInterrupted() {
	return Thread.currentThread().isInterrupted() && mInterruptible;
}

/**
 * Identify a lock
 * 
 * @param priority
 */
final private void identify(final int priority) {
	synchronized (ConcurrencyLock.this) {
		mIdentifications.add(new Identify(Thread.currentThread(), priority));
		Collections.sort(mIdentifications, mComparator);
	}
}

/**
 * Disidentify a lock
 */
final private void disidentify() {
	synchronized (ConcurrencyLock.this) {
		final Iterator<Identify> itr = mIdentifications.iterator();
		while (itr.hasNext()) {
			final Identify identify = itr.next();
			if (identify.mIdentify == Thread.currentThread())
				itr.remove();
		}
	}
}

/**
 * Wait for the top priority and block.
 */
final private int performAcquire(final long delayInMillis) {
	final long startedTime = System.currentTimeMillis();
	while (true) {
		synchronized (ConcurrencyLock.this) {
			if (mIdentifications.get(0).mIdentify == Thread.currentThread()) {
				if (!mAwait.getAndSet(true))
					break;
			}
		}
		if (isInterrupted() || (delayInMillis >= 0 && (System.currentTimeMillis() - startedTime) > delayInMillis))
			return 0;
	}
	while (mIdenityLocked) {
		if (isInterrupted() || (delayInMillis >= 0 && (System.currentTimeMillis() - startedTime) > delayInMillis))
			return 1;
		else if (mInterruptible && (mIdentify.isInterrupted() || !mIdentify.isAlive()))
			break;
	}
	mIdenityLocked = true;
	mIdentify = Thread.currentThread();
	mLockCount = 1;
	return 2;
}

/**
 * Unblock queue.
 */
final private void acquirePerformed() {
	mAwait.set(false);
}

/**
 * Lock Identify
 */
final private class Identify {
	
	// Final Private Variables
	final Thread mIdentify;
	final int mPriority;
	
	/**
	 * Constructor
	 * 
	 * @param identify
	 * @param priority
	 */
	private Identify(final Thread identify, final int priority) {
		mIdentify = identify;
		mPriority = priority;
	}
}

/**
 * Comparator
 */
final private Comparator<Identify> mComparator = new Comparator<Identify>() {
	
	/**
	 * Comparator
	 * 
	 * @param o1
	 * @param o2
	 * @return
	 */
	@Override
	public int compare(Identify o1, Identify o2) {
		return o2.mPriority - o1.mPriority;
	}
};

}[/code]

Para usar é muito simples, segue um exemplo abaixo com a utilização do ConcurrencyLock(). No exemplo é mostrado 5 threads trabalhando juntas e a trava é utilizada para criar uma operação sincronizada entres elas. E a  operação utilizada no exemplo se trata de uma simples operação Matemática, onde cada Thread faz uma operação em uma variável global. No total são realizadas 100000 operações nesta variável, o resultado nunca sera o mesmo. Mas dependendo da prioridade de cada trava, uma mesma Thread pode realizar mais vezes sua operação e outras realizarem menas vezes sua operação.

Para estabelecer uma trava é utilizado "tryAcquire(prioridade)" e para liberar esta trava é utilizado "release()". Caso necessário e você queira incrementar uma trava em uma mesma Thread apos utilizar "tryAcquire(prioridade)" é utilizado "acquire()", mas neste caso o "release()" terá de ser chamado mais de uma vez, uma para liberar o "acquire()" e outra para liberar o "tryAcquire()". 
O "tryAcquire(prioridade)" retorna "true" ou "false" dependendo de seu sucesso. Uma tentativa de trava só pode falhar quando a Thread foi interrompida ou então quando é utilizado "tryAcquire(prioridade, tempoEmMillis)" e o tempo foi excedido. Quando uma trava é adquirida em uma Thread, esta trava sera liberada automaticamente caso esta Thread seja interrompida ou então termine seu processo sem liberar a trava. Para desativar este método utilize "setInterruptible(false)", porem isso pode acarretar em um DeadLock.

Como dito, segue o exemplo que realiza varias operações Matemáticas. Se olharem bem a Thread 5 utiliza o “tryAcquire(4)” com uma prioridade de “4”, já a Thread 4 tem uma prioridade de “3”. Isso diz que a Thread 5 sera liberada mais vezes e realizara a maior quantidade de operações Matemáticas do total de operações realizado. Tentem alterar as prioridades das travas e testem para conferir o resultado.


public class Main {
	
	
	static long resultado = 0;
	static long quantidade = 100000;
	
	static int tcalled[] = new int[5];
	
	public static void main(String[] cmd) {
		final ConcurrencyLock lock = new ConcurrencyLock();
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (quantidade > 0) {
					if (lock.tryAcquire(0)) {
						if (quantidade-- > 0) {
							resultado += 1;
							tcalled[0]++;
						}
						lock.release();
					}
				}
			}
		});
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (quantidade > 0) {
					if (lock.tryAcquire(1)) {
						if (quantidade-- > 0) {
							resultado += 5;
							tcalled[1]++;
						}
						lock.release();
					}
				}
			}
		});
		
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (quantidade > 0) {
					if (lock.tryAcquire(2)) {
						if (quantidade-- > 0) {
							resultado += 10;
							tcalled[2]++;
						}
						lock.release();
					}
				}
			}
		});
		
		Thread t4 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (quantidade > 0) {
					if (lock.tryAcquire(3)) {
						if (quantidade-- > 0) {
							resultado += 15;
							tcalled[3]++;
						}
						lock.release();
					}
				}
			}
		});
		
		Thread t5 = new Thread(new Runnable() {
			@Override
			public void run() {
				while (quantidade > 0) {
					if (lock.tryAcquire(4)) {
						if (quantidade-- > 0) {
							resultado += 20;
							tcalled[4]++;
						}
						lock.release();
					}
				}
			}
		});
		
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
		
		try {
			t1.join();
			t2.join();
			t3.join();
			t4.join();
			t5.join();
		} catch (Exception e) {
		}
		
		
		int all = 0;
		for (int i = 0; i < 5; i++) {
			all += tcalled[i];
			System.out.println("Thread " + i + " realizou " + tcalled[i] + " operações.");
		}
		System.out.println("Foram realizadas " + all + " operações.");
		System.out.println("O resultado de todas operações foi: " + resultado);
	}
}

Bom uso, e caso tenham alguma duvida me perguntem. E me desculpem pelo meu Português. :frowning: