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(); } }
------
下一篇: lucene - demo