diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java new file mode 100644 index 00000000..09197048 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count.java @@ -0,0 +1,35 @@ + +package java0.conc0302.lock; + +import java.util.concurrent.locks.ReentrantLock; + +public class Count { + + final ReentrantLock lock = new ReentrantLock(); + + public void get() { +// final ReentrantLock lock = new ReentrantLock(); + try { + lock.lock(); + System.out.println(Thread.currentThread().getName() + " get begin"); + Thread.sleep(1000); + System.out.println(Thread.currentThread().getName() + " get end"); + lock.unlock(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void put() { +// final ReentrantLock lock = new ReentrantLock(); + try { + lock.lock(); + System.out.println(Thread.currentThread().getName() + " put begin"); + Thread.sleep(1000); + System.out.println(Thread.currentThread().getName() + " put end"); + lock.unlock(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java new file mode 100644 index 00000000..8cd691d1 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count2.java @@ -0,0 +1,35 @@ + +package java0.conc0302.lock; + +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class Count2 { + + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); + + public void get() { + rwLock.readLock().lock(); + try { + System.out.println(Thread.currentThread().getName() + " get begin"); + Thread.sleep(1000); + System.out.println(Thread.currentThread().getName() + " get end"); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + rwLock.readLock().unlock(); + } + } + + public void put() { + rwLock.writeLock().lock(); + try { + System.out.println(Thread.currentThread().getName() + " put begin"); + Thread.sleep(1000); + System.out.println(Thread.currentThread().getName() + " put end"); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + rwLock.writeLock().unlock(); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java new file mode 100644 index 00000000..f99eaa3e --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java @@ -0,0 +1,40 @@ + +package java0.conc0302.lock; + +public class Count3 { + + private byte[] lock1 = new byte[1]; + private byte[] lock2 = new byte[1]; + + public int num = 0; + + public void add() { + synchronized (lock1) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (lock2) { + num += 1; + } + System.out.println(Thread.currentThread().getName() + "_" + num); + } + } + + public void lockMethod() { + synchronized (lock2) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + synchronized (lock1) { + num += 1; + } + System.out.println(Thread.currentThread().getName() + "_" + num); + } + } + + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java new file mode 100644 index 00000000..e8f203e2 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/LockMain.java @@ -0,0 +1,18 @@ + +package java0.conc0302.lock; + +public class LockMain { + + public static void main(String[] args) { + Count3 count3 = new Count3(); + ThreadA threadA = new ThreadA(count3); + threadA.setName("线程A"); + threadA.start(); + + ThreadB threadB = new ThreadB(count3); + threadB.setName("线程B"); + threadB.start(); + + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java new file mode 100644 index 00000000..1dc4cee0 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ObjectCache.java @@ -0,0 +1,77 @@ + +package java0.conc0302.lock; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class ObjectCache { + + public interface ObjectFactory { + T makeObject(); + } + + class Node { + T obj; + Node next; + } + + final int capacity; + final ObjectFactory factory; + final Lock lock = new ReentrantLock(); + final Semaphore semaphore; + private Node head; + private Node tail; + + public ObjectCache(int capacity, ObjectFactory factory) { + this.capacity = capacity; + this.factory = factory; + this.semaphore = new Semaphore(this.capacity); + this.head = null; + this.tail = null; + } + + public T getObject() throws InterruptedException { + semaphore.acquire(); + return getNextObject(); + } + + private T getNextObject() { + lock.lock(); + try { + if (head == null) { + return factory.makeObject(); + } else { + Node ret = head; + head = head.next; + if (head == null) tail = null; + ret.next = null;//help GC + return ret.obj; + } + } finally { + lock.unlock(); + } + } + + private void returnObjectToPool(T t) { + lock.lock(); + try { + Node node = new Node(); + node.obj = t; + if (tail == null) { + head = tail = node; + } else { + tail.next = node; + tail = node; + } + + } finally { + lock.unlock(); + } + } + + public void returnObject(T t) { + returnObjectToPool(t); + semaphore.release(); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java new file mode 100644 index 00000000..d0ff5f98 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantLockDemo.java @@ -0,0 +1,25 @@ + +package java0.conc0302.lock; + +public class ReentrantLockDemo { + + public static void main(String[] args) { + final Count count = new Count(); + + for (int i = 0; i < 2; i++) { + new Thread() { + public void run() { + count.get(); + } + }.start(); + } + + for (int i = 0; i < 2; i++) { + new Thread() { + public void run() { + count.put(); + } + }.start(); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java new file mode 100644 index 00000000..e36e3375 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo.java @@ -0,0 +1,51 @@ + +package java0.conc0302.lock; + +public class ReentrantReadWriteLockDemo { + + public static void main(String[] args) { + final Count2 count = new Count2(); + + for (int i = 0; i < 5; i++) { + new Thread() { + public void run() { + count.get(); + } + }.start(); + } + + for (int i = 0; i < 5; i++) { + new Thread() { + public void run() { + count.put(); + } + }.start(); + } + } + + /** + * + * Thread-0 get begin + Thread-1 get begin + Thread-2 get begin + Thread-3 get begin + Thread-4 get begin + Thread-0 get end + Thread-1 get end + Thread-2 get end + Thread-4 get end + Thread-3 get end + Thread-5 put begin + Thread-5 put end + Thread-6 put begin + Thread-6 put end + Thread-7 put begin + Thread-7 put end + Thread-8 put begin + Thread-8 put end + Thread-9 put begin + Thread-9 put end + * + */ + // 读锁不互斥、写锁互斥 +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java new file mode 100644 index 00000000..7e8194a0 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java @@ -0,0 +1,47 @@ + +package java0.conc0302.lock; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReentrantReadWriteLockDemo2 { + + private final Map map = new HashMap<>(); + + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); + + public Object readWrite(String key) { + Object value = null; + System.out.println("1.首先开启读锁去缓存中取数据"); + rwLock.readLock().lock(); + try { + value = map.get(key); + if (value == null) { + System.out.println("2.数据不存在,则释放读锁,开启写锁"); + rwLock.readLock().unlock(); + rwLock.writeLock().lock(); + try { + if (value == null) { + value = "aaaa"; + } + } finally { + System.out.println("3.释放写锁"); + rwLock.writeLock().unlock(); + } + System.out.println("4.开启读锁"); + rwLock.readLock().lock(); + } + } finally { + System.out.println("5.释放读锁"); + rwLock.readLock().unlock(); + } + return value; + } + + public static void main(String[] args) { + ReentrantReadWriteLockDemo2 demo2 = new ReentrantReadWriteLockDemo2(); + demo2.readWrite("wangwei"); + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java new file mode 100644 index 00000000..5bc7d65a --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadA.java @@ -0,0 +1,15 @@ + +package java0.conc0302.lock; + +public class ThreadA extends Thread { + private Count3 count3; + + public ThreadA(Count3 count3) { + this.count3 = count3; + } + + public void run() { + count3.add(); + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java new file mode 100644 index 00000000..ee6942f1 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ThreadB.java @@ -0,0 +1,15 @@ + +package java0.conc0302.lock; + +public class ThreadB extends Thread { + private Count3 count3; + + public ThreadB(Count3 count3) { + this.count3 = count3; + } + + public void run() { + count3.lockMethod(); + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/tool/SemaphoreDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/tool/SemaphoreDemo.java new file mode 100644 index 00000000..6f43ffb1 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/tool/SemaphoreDemo.java @@ -0,0 +1,126 @@ + +package java0.conc0302.tool; + +import java.util.concurrent.Semaphore; + +public class SemaphoreDemo { + + public static void main(String[] args) { + // 启动线程 + for (int i = 0; i <= 10; i++) { + // 生产者 + new Thread(new Producer()).start(); + // 消费者 + new Thread(new Consumer()).start(); + } + } + + + // 仓库 + static Warehouse buffer = new Warehouse(); + + static class Producer implements Runnable { + + static int num = 1; + + @Override + public void run() { + int n = num++; + while (true) { + try { + buffer.put(n); + System.out.println(">" + n); + // 速度较快。休息10毫秒 + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + + static class Consumer implements Runnable { + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + while (true) { + try { + System.out.println("<" + buffer.take()); + // 速度较慢,休息1000毫秒 + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + + static class Warehouse { + // 非满锁 + final Semaphore notFull = new Semaphore(10); + // 非空锁 + final Semaphore notEmpty = new Semaphore(0); + // 核心锁 + final Semaphore mutex = new Semaphore(1); + // 库存容量 + final Object[] items = new Object[10]; + int putptr, takeptr, count; + + + /** + * 放库存 + * + * @param obj + * @throws InterruptedException + */ + public void put(Object obj) throws InterruptedException { + notFull.acquire(); + mutex.acquire(); + items[putptr] = obj; + try { + if (++putptr == items.length) { + putptr = 0; + ++count; + } + } finally { + mutex.release(); + notEmpty.release(); + } + } + + /** + * 取库存 + * + * @return + * @throws InterruptedException + */ + public Object take() throws InterruptedException { + notEmpty.acquire(); + mutex.acquire(); + Object obj = items[takeptr]; + try { + if (++takeptr == items.length) { + takeptr = 0; + --count; + } + return obj; + } finally { + mutex.release(); + notFull.release(); + } + } + } + +}