欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java lock & condition

程序员文章站 2022-06-05 18:20:42
...

 

java Lock & Condition, provide a similar, yet more extensive locking mechanism than synchronized,

 

Lock:

similar to the monitor lock used by synchronized, but more powerfull,

 

Condition:

bound to lock, provide methods similar to wait()/notify()/notifyAll() of Object,

 

------

class & interface

 

* Lock

interface of lock,

* ReentrantLock

basic implementation of Lock

* Condition

interface of condition,

* ReadWriteLock

interface, read/write version of Lock,

* ReentrantReadWriteLock

basic implementation of ReadWriteLock,


------

code

 

    lock test:

 

package eric.j2se.concurrence.lockcondition;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock test
 * 
 * @author eric
 * @date Aug 14, 2012 8:04:57 PM
 */
public class LockTest {
	private static int i;
	private static Lock lk = new ReentrantLock();

	public static void test() {
		List<Thread> list = new ArrayList<Thread>();
		int tcount = 3;
		// prepare threads
		for (int i = 0; i < tcount; i++) {
			list.add(new Thread(new TmpRunnable(), "t-" + i));
		}
		// start threads
		for (int i = 0; i < tcount; i++) {
			list.get(i).start();
		}
	}

	private static class TmpRunnable implements Runnable {
		@Override
		public void run() {
			lk.lock();
			try {
				printTime("begin");
				Thread.sleep(1000 * 1); // sleep a while, for test purpose
				printTime("end");
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lk.unlock();
			}
		}
	}

	public static void printTime() {
		printTime("");
	}

	/**
	 * print thread name & time
	 * 
	 * @param info
	 *            additional info to print
	 */
	public synchronized static void printTime(String info) {
		System.out.printf("%s:\t%d,\t,%d,\t%s\n", Thread.currentThread().getName(), ++i, System.currentTimeMillis() / 1000, info);
	}

	public static void main(String[] args) {
		test();
	}
}

 

 

    condition test:

package eric.j2se.concurrence.lockcondition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition test
 * 
 * @author eric
 * @date Aug 14, 2012 9:10:44 PM
 */
public class ConditionTest {
	private static int i;
	private static int bufSize = 26, size;
	private static char cStart = 97;
	private static char[] cbuf = new char[bufSize];

	private static Lock lk = new ReentrantLock();
	private static Condition cdEmpty = lk.newCondition();
	private static Condition cdFull = lk.newCondition();

	private static final int testInterval = 500; // interval of each step in milliseconds, for test

	/**
	 * fill buffer, start when buffer is empty
	 * 
	 * @throws InterruptedException
	 */
	public static void fill() throws InterruptedException {
		lk.lock();
		try {
			while (size == bufSize) { // buffer is full, wait for condition empty
				cdEmpty.await();
			}

			System.out.printf("\n\n------\nstart fill\n\n");
			while (size < bufSize) { // buffer is not full now, fill it
				char c = (char) (cStart + size);
				cbuf[size++] = c;
				printTime("put: " + new Character(c));
				Thread.sleep(testInterval);
			}
			cdFull.signal(); // buffer is full filled now, need to be read
			System.out.printf("\nbuffer full\n------\n\n");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lk.unlock();
		}
	}

	/**
	 * take from buffer & empty it, start when buffer is full
	 * 
	 * @throws InterruptedException
	 */
	public static void take() throws InterruptedException {
		lk.lock();
		try {
			while (size != bufSize) { // not full, wait for condition full
				cdFull.await();
			}
			System.out.printf("\n\n------\nstart take\n\n");
			for (int i = 0; i < bufSize; i++) { // now is full, take
				printTime("take: " + new Character(cbuf[i]));
				size--;
				Thread.sleep(testInterval);
			}
			cdEmpty.signal(); // buffer is empty now, need to be fill
			System.out.printf("\nbuffer empty\n------\n\n");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lk.unlock();
		}
	}

	public static void test() {
		// thread to fill buffer
		Thread tFill = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while (true)
						fill();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "t-fill");

		// thread to take from buffer
		Thread tTake = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while (true)
						take();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "t-take");
		tTake.start();
		tFill.start();
	}

	public static void printTime() {
		printTime("");
	}

	/**
	 * print thread name & time
	 * 
	 * @param info
	 *            additional info to print
	 */
	public synchronized static void printTime(String info) {
		System.out.printf("%s:\t%d,\t,%d,\t%s\n", Thread.currentThread().getName(), ++i, System.currentTimeMillis() / 1000, info);
	}

	public static void main(String[] args) {
		test();
	}
}
 

 

    read/write lock test:

package eric.j2se.concurrence.lockcondition;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Read Write Lock test
 * 
 * @author eric
 * @date Aug 14, 2012 10:34:08 PM
 */
public class ReadWriteLockTest {
	private static int i;

	private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private static Lock rlk = lock.readLock();
	private static Lock wlk = lock.writeLock();

	private static String data = "";

	private static volatile long lastUpdate; // track last publish date

	/**
	 * publish data, use write lock,
	 * 
	 * @param newData
	 */
	public static void publish(String newData) {
		wlk.lock();
		try {
			printTime("begin publish");
			data = newData;
			lastUpdate = System.currentTimeMillis(); // modify last update date
			printTime("data:\n\t" + data);
			printTime("end publish");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			wlk.unlock();
		}
	}

	/**
	 * view data, use read lock
	 * 
	 * @param previousView
	 *            last viewed publish date
	 * @return date of new publish, or -1 if no new publish
	 */
	public static long view(long previousView) {
		if (previousView < lastUpdate) { // new publish
			rlk.lock();
			try {
				printTime("view data:\n\t" + data);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				rlk.unlock();
			}
			return lastUpdate;
		} else { // no new publish
			printTime("no new publish yet");
			return -1;
		}
	}

	public static void test() throws InterruptedException {
		Thread tPublish = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					publish("hi, xxxxxx, data_" + i + "_xxxxxx");
					try {
						Thread.sleep(1000 * 10); // update interval
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}, "t-publish");

		// prepare view threads
		int tViewCount = 3; // count of view thread
		List<Thread> tViewList = new ArrayList<Thread>();
		final List<Long> tLastView = new ArrayList<Long>(); // keep track of last viewed publish date
		for (int i = 0; i < tViewCount; i++) {
			final int _index = i;
			tViewList.add(new Thread(new Runnable() {
				@Override
				public void run() {
					while (true) {
						long _lastDate = view(tLastView.get(_index));
						if (_lastDate > 0) {
							tLastView.set(_index, _lastDate); // update last viewed publish date, if has new publish
						}
						try {
							Thread.sleep(1000 * 4); // view interval
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}, "t-view-" + i));
			tLastView.add(0L);
		}

		tPublish.start();
		for (int i = 0; i < tViewCount; i++) {
			tViewList.get(i).start();
			Thread.sleep(1000 * 5); // start interval of view threads
		}
	}

	public static void printTime() {
		printTime("");
	}

	/**
	 * print thread name & time
	 * 
	 * @param info
	 *            additional info to print
	 */
	public synchronized static void printTime(String info) {
		System.out.printf("%s:\t%d,\t,%d,\t%s\n", Thread.currentThread().getName(), ++i, System.currentTimeMillis() / 1000, info);
	}

	public static void main(String[] args) throws InterruptedException {
		test();
	}
}
 


------