diff --git a/02nio/nio01/pom.xml b/02nio/nio01/pom.xml index e42a62f2..8ba80b9b 100644 --- a/02nio/nio01/pom.xml +++ b/02nio/nio01/pom.xml @@ -59,6 +59,11 @@ netty-all 4.1.51.Final + + com.squareup.okhttp3 + okhttp + 4.9.0 + diff --git a/03concurrency/0301/pom.xml b/03concurrency/0301/pom.xml index 55691a2d..3a8878fb 100644 --- a/03concurrency/0301/pom.xml +++ b/03concurrency/0301/pom.xml @@ -19,6 +19,14 @@ + + + junit + junit + 4.11 + compile + + \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java index 5fec537e..5be8f3ef 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/DaemonThread.java @@ -1,5 +1,10 @@ package java0.conc0301; +/** + * 总结: + * JAVA 进程中,如果运行的线程都是 daemon 线程,则进程可以正常结束, + * 如果运行的线程中有非 daemon 线程,则进程需要等待所有的非daemon线程都运行完毕,才能正常结束。 + */ public class DaemonThread { public static void main(String[] args) throws InterruptedException { diff --git a/03concurrency/0301/src/main/java/java0/conc0301/Runner2.java b/03concurrency/0301/src/main/java/java0/conc0301/Runner2.java index d80e8c14..d91aa0fd 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/Runner2.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/Runner2.java @@ -1,5 +1,9 @@ package java0.conc0301; +/** + * Thread.isInterrupted() 不会重置 Interrupted 状态 + * Thread.interrupted() 重置 Interrupted 状态 + */ public class Runner2 implements Runnable { @Override diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java b/03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java index 8e13af9e..2898a07d 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/ThreadCount.java @@ -1,5 +1,17 @@ package java0.conc0301; +/** + * 线程信息: + * 在没有业务线程情况下,总共有两个线程组,6个线程(4个系统组的线程,2个主线程组的线程),如下所示: + * java.lang.ThreadGroup[name=system,maxpri=10] + * Thread[Reference Handler,10,system] + * Thread[Finalizer,8,system] + * Thread[Signal Dispatcher,9,system] + * Thread[Attach Listener,5,system] + * java.lang.ThreadGroup[name=main,maxpri=10] + * Thread[main,5,main] + * Thread[Monitor Ctrl-Break,5,main] + */ public class ThreadCount { public static void main(String[] args) throws InterruptedException { //System.out.println("system:"+Thread.currentThread().getThreadGroup().getParent()); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java b/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java index b365b40c..a1880779 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/ThreadMain2.java @@ -9,12 +9,16 @@ public static void main(String[] args) { new Thread(threadB, "线程名称:(" + i + ")").start(); } + Thread.currentThread().getThreadGroup().list(); + try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } + System.out.println("线程组成员:"); + //返回对当前正在执行的线程对象的引用 Thread threadMain = Thread.currentThread(); System.out.println("这是主线程:"); diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java index 1cbf6a5a..bf976071 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/Join.java @@ -1,12 +1,21 @@ package java0.conc0301.op; +/** + * 总结:线程A结束的时候,JVM内部会发送通知 notifyAll 给该线程对象A上的等待线程,唤醒在线程对象A上等待的线程 + * 其中this 代表线程的执行的task对象。 + * JAVA线程可以看作由两部分组成, + * 1. Java Task 对象,由JVM回调执行线程中的任务,即run方法的对象实体。 + * 2. 操作系统的线程,一个Java 线程会一对一一个操作系统线程, + * 而Thread 中的 this对象代表Java Task 对象实体, + * Thread.current()返回的线程代表的是操作系统线程 + */ public class Join { public static void main(String[] args) { Object oo = new Object(); MyThread thread1 = new MyThread("thread1 -- "); - //oo = thread1; + oo = thread1; thread1.setOo(oo); thread1.start(); @@ -42,10 +51,12 @@ public MyThread(String name) { @Override public void run() { - synchronized (oo) { // 这里用oo或this,效果不同 + synchronized (this) { // 这里用oo或this,效果不同 for (int i = 0; i < 100; i++) { System.out.println(name + i); } + //my Test: add notifyAll to solve dead lock + //oo.notifyAll(); } } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java b/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java index e3956c10..e0059237 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/op/WaitAndNotify.java @@ -37,7 +37,10 @@ public static void main(String[] args) { class MethodClass { // 定义生产最大量 private final int MAX_COUNT = 20; - + + /** + * 单线程创建 product, 不需要加锁 + */ int productCount = 0; public synchronized void product() throws InterruptedException { diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java b/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java index 68d869f6..b5e47132 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/sync/Counter.java @@ -1,5 +1,8 @@ package java0.conc0301.sync; +/** + * volatile 只能保证有序性和可见性,不能保证原子性 + */ public class Counter { public final static int A=10; diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java index 4dc7513f..6f5cb550 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread1.java @@ -1,11 +1,19 @@ package java0.conc0301.sync; + +/** + * Thread 线程对象中的任意方法获取的 this 代表线程对象本身,并不代表线程信息(线程信息中包括操作系统线程) + * Thread.currentThread() 代表操作系统对应的线程信息. + * 所以 this != Thread.currentThread() ,this 代表 Task 对象信息 + * 如下所示:TA 线程和 TB线程在操作系统上创建了两个操作系统线程对应 A线程 和 B线程,但是它们公用一个Task 对象信息, this是 task 对象信息 + */ public class Thread1 implements Runnable { @Override public void run() { synchronized (this) { + System.out.println(this); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); } @@ -14,8 +22,10 @@ public void run() { public static void main(String[] args) { Thread1 t1 = new Thread1(); + System.out.println("the Thread1 obj t1:" + t1); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); + ta.start(); tb.start(); } diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java index d0f0638b..741ee3cd 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread2.java @@ -1,6 +1,10 @@ package java0.conc0301.sync; +/** + * 总结: + * 两个Java Thread 对应两个操作系统线程,同时同享一个java task 对象实例 + */ public class Thread2 { public void m4t1() { diff --git a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java index f9d5d742..4c3cef9f 100644 --- a/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java +++ b/03concurrency/0301/src/main/java/java0/conc0301/sync/Thread3.java @@ -14,7 +14,7 @@ private void m4t1() { } } - private void m4t2() { + private synchronized void m4t2() { int i = 5; while (i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java b/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java index cece1ec3..85270bb6 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicCount.java @@ -3,7 +3,7 @@ import java.util.concurrent.atomic.AtomicInteger; -public class AtomicCount { +public class AtomicCount implements CountInf { private AtomicInteger num = new AtomicInteger(); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java b/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java index 297eb343..5700aedf 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/atomic/AtomicMain.java @@ -1,16 +1,23 @@ package java0.conc0302.atomic; +/** + * SyncCount 使用公平锁处理共享资源, + * 由于公平锁效率较低,所有5s内没有完成计算,就返回总和,所以结果错误. + * 同样时间非公平锁5s内可以完成计算,结果正确。 + * 时间增加到10s后结果正确。 + * + */ public class AtomicMain { public static void main(String[] args) { - final SyncCount count = new SyncCount(); + final CountInf count = new SyncCount(); for (int i = 0; i < 100; i++) { new Thread(new Runnable() { @Override public void run() { for (int j = 0; j < 10000; j++) { - count.add(); + count.add(); } } }).start(); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java b/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java index 02fd13d5..9c648002 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/atomic/Count.java @@ -1,7 +1,7 @@ package java0.conc0302.atomic; -public class Count { +public class Count implements CountInf{ private int num = 0; diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java index 6a7356c6..3a5fedaa 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/atomic/LongDemo.java @@ -3,6 +3,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; +/** + * + */ public class LongDemo { public static void main(String[] args) { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java b/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java index b95c7cff..d1d206fe 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/atomic/SyncCount.java @@ -4,7 +4,13 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -public class SyncCount { +/** + * 总结:公平锁不能保证原子性 + * 非公平锁可以保证原子性, + * 为什么?? + * + */ +public class SyncCount implements CountInf { private int num = 0; diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java index 33ad0bab..0155cd7f 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ConditionDemo.java @@ -42,4 +42,39 @@ public Object take() throws InterruptedException { lock.unlock(); } } + + public static void main(String[] args){ + ConditionDemo test = new ConditionDemo(); + + Thread putThread = new Thread(new Runnable() { + @Override + public void run() { + for(int i=0;i<1000;i++){ + try { + test.put(i); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }); + putThread.setName("putThread"); + putThread.start(); + + Thread takeThread = new Thread(new Runnable() { + @Override + public void run() { + for(int i=0;i<1000;i++){ + try { + test.take(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }); + takeThread.setName("takeThread"); + takeThread.start(); + + } } \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java index f99eaa3e..01c94759 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/Count3.java @@ -1,6 +1,14 @@ package java0.conc0302.lock; +/** + * 总结: + * 死锁场景: + * 获取多把锁的顺序和释放多把锁的顺序不一致,导致死锁 + * 产生死锁的必要条件: + * 1. 已经获取锁,尝试获取其他锁 + * 2. 获取锁过程中不可中断或超时 + */ public class Count3 { private byte[] lock1 = new byte[1]; diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java index 18f598f1..066e8fee 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/LockSupportDemo.java @@ -2,6 +2,15 @@ import java.util.concurrent.locks.LockSupport; +/** + * 总结:LockSupport.park(t1) 休眠本线程t1后,并不释放锁信息,或者可以理解为与锁信息无关, + * LockSupport.park(t1) 仅仅是休眠线程t1。 + * + * 唤醒被LockSupport.park()的线程,可以在其他线程中通过两种方式唤醒: + * 1. LockSupport.unpark(t1); + * 2. t1.interrupt() + * + */ public class LockSupportDemo { public static Object u = new Object(); diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java index 82b4001b..e18e26ba 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo2.java @@ -19,6 +19,7 @@ public Object readWrite(String key) { value = map.get(key); if (value == null) { System.out.println("2.数据不存在,则释放读锁,开启写锁"); + // 锁升级 rwLock.readLock().unlock(); rwLock.writeLock().lock(); try { diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo3.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo3.java new file mode 100644 index 00000000..9cd34b11 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/ReentrantReadWriteLockDemo3.java @@ -0,0 +1,50 @@ +package java0.conc0302.lock; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class ReentrantReadWriteLockDemo3 { + 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"; + } + /** + * 锁降级,可以使本线程一直占有锁, + * 如果不使用锁降级,需要释放写锁,再重新获取读锁,在这个过程中可能长时间无法获取读锁 + * 锁降级则可以直接获取读锁,防止其他线程竞争读资源 + */ + System.out.println("3.设置数据成功,写锁降级降为读锁"); + rwLock.readLock().lock(); + } finally { + System.out.println("4.释放写锁"); + rwLock.writeLock().unlock(); + } + } + } finally { + System.out.println("5.释放读锁"); + rwLock.readLock().unlock(); + } + return value; + } + + public static void main(String[] args) { + ReentrantReadWriteLockDemo3 demo3 = new ReentrantReadWriteLockDemo3(); + demo3.readWrite("bingfabiancheng"); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java b/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java index 1dc47538..d230c964 100644 --- a/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java +++ b/03concurrency/0301/src/main/java/java0/conc0302/lock/TestFair.java @@ -3,6 +3,10 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; +/** + * 总结:非公平锁是公平锁效率的100多倍 + * 等待所有累加线程都结束,可以通过记录尾启动业务线程前的线程总数。 + */ public class TestFair { public static volatile int race=0; public static ReentrantLock lock = new ReentrantLock(true); // 改成false会好100倍 @@ -16,7 +20,7 @@ public static void main(String[]args){ int count = Thread.activeCount(); long now = System.currentTimeMillis(); System.out.println(count); - AtomicReference sign =new AtomicReference<>(); + //AtomicReference sign =new AtomicReference<>(); Thread[]threads=new Thread[THREADS_COUNT]; //定义20个线程 for(int i=0;i list = new ArrayList(); // List list = new LinkedList<>(); - List list = new Vector<>(); + // List list = new Vector<>(); // 只有CopyOnWriteArrayList 安全,不报错 - //List list = new CopyOnWriteArrayList(); + List list = new CopyOnWriteArrayList(); for (int i = 0; i < 10000; i++) { diff --git a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java b/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java index 82718cdb..ab2ca0f4 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/collection/CopyOnWriteArrayListDemo1.java @@ -6,11 +6,13 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - +/** + * + */ public class CopyOnWriteArrayListDemo1 { private static final int THREAD_POOL_MAX_NUM = 10; - private List mList = new ArrayList(); // ArrayList 无法运行 - //private List mList = new CopyOnWriteArrayList<>(); + //private List mList = new ArrayList(); // ArrayList 无法运行 + private List mList = new CopyOnWriteArrayList<>(); public static void main(String args[]) { new CopyOnWriteArrayListDemo1().start(); @@ -43,7 +45,7 @@ public ListReader(List list) { public void run() { if (this.mList != null) { for (String str : this.mList) { - System.out.println(Thread.currentThread().getName() + " : " + str); + System.out.println(Thread.currentThread().getName() + " read data: " + str); } } } @@ -62,6 +64,7 @@ public ListWriter(List list, int index) { public void run() { if (this.mList != null) { //this.mList.remove(this.mIndex); + System.out.println(Thread.currentThread().getName() + " write data:"+mIndex); this.mList.add("...... add " + mIndex + " ......"); } } diff --git a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java b/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java index 14a16383..d3ce629f 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/future/FutureDemo1.java @@ -8,6 +8,7 @@ public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool(); Future result = executor.submit(new Callable() { public Integer call() throws Exception { + Thread.sleep(1000); return new Random().nextInt(); } }); diff --git a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java b/03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java index 69499819..4783c9ee 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/future/FutureTask1.java @@ -6,7 +6,7 @@ public class FutureTask1 { public static void main(String[] args) { //第一种方式 - FutureTask task = new FutureTask(new Callable() { + FutureTask task = new FutureTask<>(new Callable() { @Override public Integer call() throws Exception { return new Random().nextInt(); diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResult.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResult.java new file mode 100644 index 00000000..2e402e11 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResult.java @@ -0,0 +1,16 @@ +package java0.conc0303.homework; + +public interface AsyncResult { + + int getResult() throws Exception; + + default int sum() { + return fibo(36); + } + + default int fibo(int a) { + if ( a < 2) + return 1; + return fibo(a-1) + fibo(a-2); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl1.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl1.java new file mode 100644 index 00000000..1ae62f30 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl1.java @@ -0,0 +1,24 @@ +package java0.conc0303.homework; + +/** + * 应用 volatile 机制 + */ +public class AsyncResultImpl1 implements AsyncResult { + private volatile int result = -1; + private volatile boolean hadComputed = false; + @Override + public int getResult() throws Exception { + new Thread(new Runnable() { + @Override + public void run() { + result = sum(); + hadComputed = true; + } + }).start(); + + while (!hadComputed){ + Thread.yield();// 防止main线程一直占用CPU资源 + } + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl10.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl10.java new file mode 100644 index 00000000..6607fdc2 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl10.java @@ -0,0 +1,22 @@ +package java0.conc0303.homework; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +/** + * 应用阻塞队列 + */ +public class AsyncResultImpl10 implements AsyncResult { + private BlockingQueue blockingQueue = new ArrayBlockingQueue<>(1); + @Override + public int getResult() throws Exception { + new Thread(new Runnable() { + @Override + public void run() { + blockingQueue.offer(sum()); + } + }).start(); + + return blockingQueue.take(); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl2.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl2.java new file mode 100644 index 00000000..0d321b2b --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl2.java @@ -0,0 +1,29 @@ +package java0.conc0303.homework; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 应用CAS机制 + */ +public class AsyncResultImpl2 implements AsyncResult { + + private volatile int result = -1; + + private AtomicInteger tag = new AtomicInteger(1); + + @Override + public int getResult() throws Exception { + new Thread(new Runnable() { + @Override + public void run() { + result = sum(); + tag.getAndDecrement(); + } + }).start(); + + while (tag.get() > 0){ + Thread.yield(); + } + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl3.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl3.java new file mode 100644 index 00000000..664b84ff --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl3.java @@ -0,0 +1,21 @@ +package java0.conc0303.homework; + +/** + * 应用join 机制 + */ +public class AsyncResultImpl3 implements AsyncResult { + private volatile int result = -1; + @Override + public int getResult() throws Exception { + Thread t1 = new Thread(new Runnable() { + @Override + public void run() { + result = sum(); + } + }); + t1.start(); + t1.join(); + + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl4.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl4.java new file mode 100644 index 00000000..7a0991b8 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl4.java @@ -0,0 +1,27 @@ +package java0.conc0303.homework; + +/** + * 应用传统的synchronized锁通知机制 + */ +public class AsyncResultImpl4 implements AsyncResult { + private volatile int result = -1; + private final Object getResultLock = new Object(); + + @Override + public int getResult() throws Exception { + new Thread(new Runnable() { + @Override + public void run() { + synchronized (getResultLock) { + result = sum(); + getResultLock.notifyAll(); + } + } + }).start(); + + synchronized (getResultLock) { + getResultLock.wait(); + return result; + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl5.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl5.java new file mode 100644 index 00000000..17f7a78b --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl5.java @@ -0,0 +1,34 @@ +package java0.conc0303.homework; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +public class AsyncResultImpl5 implements AsyncResult { + private volatile int result = -1; + + @Override + public int getResult() throws Exception { + final ReentrantLock lock = new ReentrantLock(false); + Condition hadCompute = lock.newCondition(); + new Thread(new Runnable() { + @Override + public void run() { + lock.lock(); + try { + result = sum(); + hadCompute.signalAll(); + }finally { + lock.unlock(); + } + } + }).start(); + + lock.lock(); + try { + hadCompute.await(); + return result; + }finally { + lock.unlock(); + } + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl6.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl6.java new file mode 100644 index 00000000..96080ce8 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl6.java @@ -0,0 +1,23 @@ +package java0.conc0303.homework; + +import java.util.concurrent.CountDownLatch; + +/** + * 应用CountDownLatch机制 + */ +public class AsyncResultImpl6 implements AsyncResult{ + private volatile int result = -1; + @Override + public int getResult() throws Exception { + CountDownLatch countDownLatch = new CountDownLatch(1); + new Thread(new Runnable() { + @Override + public void run() { + result = sum(); + countDownLatch.countDown(); + } + }).start(); + countDownLatch.await(); + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl7.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl7.java new file mode 100644 index 00000000..14cc4152 --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl7.java @@ -0,0 +1,27 @@ +package java0.conc0303.homework; + +import java.util.concurrent.CyclicBarrier; + +/** + * 应用 CyclicBarrier 机制 + */ +public class AsyncResultImpl7 implements AsyncResult { + private volatile int result = -1; + @Override + public int getResult() throws Exception { + final CyclicBarrier cyclicBarrier = new CyclicBarrier(2); + new Thread(new Runnable() { + @Override + public void run() { + try { + result = sum(); + cyclicBarrier.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + cyclicBarrier.await(); + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl8.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl8.java new file mode 100644 index 00000000..c69d4c7d --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl8.java @@ -0,0 +1,29 @@ +package java0.conc0303.homework; + +import java.util.concurrent.Semaphore; + +/** + * 应用Semaphore机制 + */ +public class AsyncResultImpl8 implements AsyncResult { + private volatile int result = -1; + + @Override + public int getResult() throws Exception { + final Semaphore semaphore = new Semaphore(2); + semaphore.acquire(1); + new Thread(new Runnable() { + @Override + public void run() { + try { + result = sum(); + }finally { + semaphore.release(1); + } + } + }).start(); + + semaphore.acquire(2); + return result; + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl9.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl9.java new file mode 100644 index 00000000..de68464f --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/AsyncResultImpl9.java @@ -0,0 +1,25 @@ +package java0.conc0303.homework; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * 应用Future机制 + */ +public class AsyncResultImpl9 implements AsyncResult{ + @Override + public int getResult() throws Exception{ + ExecutorService executorService = Executors.newFixedThreadPool(1); + Future future = executorService.submit(new Callable() { + @Override + public Integer call() { + return sum(); + } + }); + // 注意关闭线程池,否则main线程不会结束,会一直等待,直到线程池被关闭。 + executorService.shutdown(); + return future.get(); + } +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/homework/Homework.java b/03concurrency/0301/src/main/java/java0/conc0303/homework/Homework.java new file mode 100644 index 00000000..d85ff7df --- /dev/null +++ b/03concurrency/0301/src/main/java/java0/conc0303/homework/Homework.java @@ -0,0 +1,99 @@ +package java0.conc0303.homework; + +import org.junit.Test; + +/** + * 本周作业:(必做)思考有多少种方式,在main函数启动一个新线程或线程池, + * 异步运行一个方法,拿到这个方法的返回值后,退出主线程? + * 写出你的方法,越多越好,提交到github。 + * + * 一个简单的代码参考: + */ + +public class Homework { + + /* public static void main(String[] args) throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl5(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + }*/ + @Test + public void test1() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl1(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + + @Test + public void test2() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl2(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + + @Test + public void test3() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl3(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + + @Test + public void test4() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl4(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + + @Test + public void test6() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl6(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + @Test + public void test7() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl7(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + @Test + public void test8() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl8(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + @Test + public void test9() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl9(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + @Test + public void test10() throws Exception { + long start=System.currentTimeMillis(); + AsyncResult asyncResult = new AsyncResultImpl10(); + System.out.println("异步计算结果为:"+ asyncResult.getResult()); + System.out.println("使用时间:"+ (System.currentTimeMillis()-start) + " ms"); + System.out.println("退出main线程"); + } + +} diff --git a/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java b/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java index bbfe35e0..411cf984 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/threadlocal/ThreadLocalDemo.java @@ -1,5 +1,8 @@ package java0.conc0303.threadlocal; +/** + * Thread level variable: ThreadLocal + */ public class ThreadLocalDemo { private static ThreadLocal seqNum = new ThreadLocal() { diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java b/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java index b93731be..5e847033 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/tool/CountDownLatchDemo.java @@ -2,6 +2,9 @@ import java.util.concurrent.CountDownLatch; +/** + * CountDownLatch 各个线程相对独立影响CountDownLatch 状态,最后在主线程上汇聚 + */ public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(5); @@ -22,12 +25,12 @@ public readNum(int id,CountDownLatch latch){ } @Override public void run() { - synchronized (this){ + //synchronized (this){ System.out.println("id:"+id+","+Thread.currentThread().getName()); //latch.countDown(); System.out.println("线程组任务"+id+"结束,其他任务继续"); latch.countDown(); - } + //} } } } \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java b/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java index 628d980d..58b2d14d 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/tool/CyclicBarrierDemo.java @@ -2,6 +2,11 @@ import java.util.concurrent.CyclicBarrier; +/** + * CyclicBarrier 线程之间不相关独立,随着线程影响CyclicBarrier的状态,线程间状态相互影响, + * 当线程内部到达cyc.await() 进行阻塞,直到所有线程都达到cyc.await()处,内部线程进行执行, + * 最后到达cyc.await()的线程,还会调用回调函数的run方法,进行回调处理。 + */ public class CyclicBarrierDemo { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() { @@ -36,16 +41,16 @@ public readNum(int id,CyclicBarrier cyc){ } @Override public void run() { - synchronized (this){ + //synchronized (this){ System.out.println("id:"+id+","+Thread.currentThread().getName()); try { - cyc.await(); + ///cyc.await(); System.out.println("线程组任务" + id + "结束,其他任务继续"); - //cyc.await(); // 注意跟CountDownLatch不同,这里在子线程await + cyc.await(); // 注意跟CountDownLatch不同,这里在子线程await } catch (Exception e) { e.printStackTrace(); } - } + //} } } } \ No newline at end of file diff --git a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java b/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java index 2acb724a..8fc605fa 100644 --- a/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java +++ b/03concurrency/0301/src/main/java/java0/conc0303/tool/SemaphoreDemo2.java @@ -19,6 +19,7 @@ public static void main(String[] args) throws Exception { exec.execute(() -> { try { semaphore.acquire(3); // 获取全部许可,退化成串行执行 + Thread.sleep(3000); test(threadNum); semaphore.release(3); // 释放多个许可 } catch (Exception e) {