From a1cdd147ea5b8838fa5fd0d96aae4fe311688c7a Mon Sep 17 00:00:00 2001 From: northleafup Date: Thu, 26 Mar 2020 11:00:13 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8E=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E7=9B=B8=E5=85=B3=E7=9A=84=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/compiler.xml | 13 - .idea/encodings.xml | 63 -- .idea/misc.xml | 14 - .idea/vcs.xml | 6 - .idea/workspace.xml | 1002 --------------------- JUC.iml | 2 - target/classes/META-INF/JUC.kotlin_module | Bin 16 -> 0 bytes target/classes/Test.puml | 7 - 8 files changed, 1107 deletions(-) delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml delete mode 100644 JUC.iml delete mode 100644 target/classes/META-INF/JUC.kotlin_module delete mode 100644 target/classes/Test.puml diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 5850ed7..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 46fa993..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 803a716..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 35ee93a..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,1002 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - synchronized - compare - incrementand - compareandset - all - sun.mi - onadv - set - synchronizedMap - synchronizedList - Fork - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1565232818446 - - - 1566616292953 - - - 1567908240513 - - - 1569205605236 - - - 1569727444423 - - - 1570803022734 - - - 1571235524344 - - - 1573357300351 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file://$PROJECT_DIR$/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java - 12 - - - - jar://C:/Program Files/Java/jdk-11.0.3/lib/src.zip!/java.base/java/util/concurrent/locks/ReentrantLock.java - 126 - - - - file://$PROJECT_DIR$/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java - 10 - - - - jar://C:/Program Files/Java/jdk1.7.0_80/src.zip!/java/util/concurrent/ConcurrentHashMap.java - 807 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No facets are configured - - - - - - - - - - - - - - - 11 - - - - - - - - JUC - - - - - - - - Maven: com.lmax:disruptor:3.4.2 - - - - - - - - \ No newline at end of file diff --git a/JUC.iml b/JUC.iml deleted file mode 100644 index 74f3f13..0000000 --- a/JUC.iml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/target/classes/META-INF/JUC.kotlin_module b/target/classes/META-INF/JUC.kotlin_module deleted file mode 100644 index 8fb60192d378759239a3ecbf60eac8c8de446e9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16 RcmZQzU|?ooU|@t|UH|}6022TJ diff --git a/target/classes/Test.puml b/target/classes/Test.puml deleted file mode 100644 index d0f7d79..0000000 --- a/target/classes/Test.puml +++ /dev/null @@ -1,7 +0,0 @@ -@startuml -Alice -> Bob: Authentication Request -Bob --> Alice: Authentication Response - -Alice -> Bob: Another authentication Request -Alice <-- Bob: another authentication Response -@enduml \ No newline at end of file From 85813ff74397eced3dc354d33582372f3f13600b Mon Sep 17 00:00:00 2001 From: northleafup Date: Thu, 26 Mar 2020 12:22:46 +0800 Subject: [PATCH 2/3] convert gbk to utf-8 --- .../juc/c_000/T02_HowToCreateThread.java | 2 +- src/main/java/com/mashibing/juc/c_001/T.java | 6 +-- src/main/java/com/mashibing/juc/c_002/T.java | 6 +-- src/main/java/com/mashibing/juc/c_003/T.java | 6 +-- src/main/java/com/mashibing/juc/c_003/T1.java | 8 ++-- src/main/java/com/mashibing/juc/c_004/T.java | 8 ++-- src/main/java/com/mashibing/juc/c_005/T.java | 2 +- src/main/java/com/mashibing/juc/c_006/T.java | 2 +- src/main/java/com/mashibing/juc/c_007/T.java | 4 +- .../java/com/mashibing/juc/c_008/Account.java | 10 ++-- src/main/java/com/mashibing/juc/c_009/T.java | 4 +- src/main/java/com/mashibing/juc/c_010/T.java | 6 +-- src/main/java/com/mashibing/juc/c_011/T.java | 12 ++--- .../juc/c_012_Volatile/T01_HelloVolatile.java | 20 ++++---- .../T02_VolatileReference1.java | 4 +- .../T03________VolatileReference2.java | 2 +- .../c_012_Volatile/T04_VolatileNotSync.java | 4 +- .../c_012_Volatile/T05_VolatileVsSync.java | 2 +- .../FineCoarseLock.java | 12 ++--- .../c_017_MoreAboutSync/DoNotLockString.java | 10 ++-- .../c_017_MoreAboutSync/SyncSameObject.java | 12 ++--- .../c_018_00_AtomicXXX/T01_AtomicInteger.java | 4 +- .../juc/c_020/T01_ReentrantLock1.java | 6 +-- .../juc/c_020/T02_ReentrantLock2.java | 12 ++--- .../juc/c_020/T03_ReentrantLock3.java | 20 ++++---- .../juc/c_020/T04_ReentrantLock4.java | 22 ++++----- .../juc/c_020/T05_ReentrantLock5.java | 24 +++++----- .../juc/c_020/T07_TestCyclicBarrier.java | 4 +- .../mashibing/juc/c_020/T08_TestPhaser.java | 14 +++--- .../mashibing/juc/c_020/T09_TestPhaser2.java | 22 ++++----- .../juc/c_020/T10_TestReadWriteLock.java | 4 +- .../juc/c_020/T11_TestSemaphore.java | 2 +- .../T01_WithoutVolatile.java | 10 ++-- .../c_020_01_Interview/T02_WithVolatile.java | 16 +++---- .../T03_NotifyHoldingLock.java | 26 +++++------ .../T04_NotifyFreeLock.java | 34 +++++++------- .../T05_CountDownLatch.java | 46 +++++++++---------- .../c_020_01_Interview/T06_LockSupport.java | 42 ++++++++--------- .../T07_LockSupport_WithoutSleep.java | 42 ++++++++--------- .../juc/c_020_01_Interview/T08_Semaphore.java | 4 +- .../juc/c_021_01_interview/MyContainer1.java | 18 ++++---- .../juc/c_021_01_interview/MyContainer2.java | 22 ++++----- .../com/mashibing/juc/c_021_02_AQS/MLock.java | 4 +- .../juc/c_021_02_AQS/TestReentrantLock.java | 2 +- .../T02_SoftReference.java | 12 ++--- .../T03_WeakReference.java | 2 +- .../T04_PhantomReference.java | 30 ++++++------ .../ThreadLocal1.java | 4 +- .../ThreadLocal2.java | 10 ++-- .../com/mashibing/juc/c_023/Singleton.java | 8 ++-- .../TicketSeller1.java | 16 +++---- .../TicketSeller2.java | 18 ++++---- .../TicketSeller3.java | 24 +++++----- .../TicketSeller4.java | 26 +++++------ .../juc/c_025/T01_ConcurrentMap.java | 4 +- .../juc/c_025/T02_CopyOnWriteList.java | 10 ++-- .../juc/c_025/T04_ConcurrentQueue.java | 2 +- .../juc/c_025/T05_LinkedBlockingQueue.java | 4 +- .../juc/c_025/T06_ArrayBlockingQueue.java | 2 +- .../juc/c_025/T08_SynchronusQueue.java | 4 +- .../A1B2C3/T01_00_Question.java | 2 +- .../A1B2C3/T02_00_LockSupport.java | 10 ++-- .../c_026_00_interview/A1B2C3/T03_00_cas.java | 2 +- .../A1B2C3/T06_00_sync_wait_notify.java | 6 +-- .../A1B2C3/T09_00_lock_condition.java | 2 +- .../c_026_01_ThreadPool/T01_MyExecutor.java | 2 +- .../T02_ExecutorService.java | 4 +- .../juc/c_026_01_ThreadPool/T03_Callable.java | 8 ++-- .../c_026_01_ThreadPool/T04_Executors.java | 2 +- .../c_026_01_ThreadPool/T05_ThreadPool.java | 2 +- .../c_026_01_ThreadPool/T06_00_Future.java | 6 +-- .../T06_01_CompletableFuture.java | 6 +-- .../T09_FixedThreadPool.java | 2 +- .../T11_WorkStealingPool.java | 2 +- .../T13_ParallelStreamAPI.java | 2 +- .../juc/c_027_future_to_loom/T01_Future.java | 8 ++-- .../T02_ListenableFuture.java | 2 +- 77 files changed, 393 insertions(+), 393 deletions(-) diff --git a/src/main/java/com/mashibing/juc/c_000/T02_HowToCreateThread.java b/src/main/java/com/mashibing/juc/c_000/T02_HowToCreateThread.java index ce1f3a7..c157d09 100644 --- a/src/main/java/com/mashibing/juc/c_000/T02_HowToCreateThread.java +++ b/src/main/java/com/mashibing/juc/c_000/T02_HowToCreateThread.java @@ -25,4 +25,4 @@ public static void main(String[] args) { } -//请你告诉我启动线程的三种方式 1:Thread 2: Runnable 3:Executors.newCachedThrad +//璇蜂綘鍛婅瘔鎴戝惎鍔ㄧ嚎绋嬬殑涓夌鏂瑰紡 1锛歍hread 2: Runnable 3:Executors.newCachedThrad diff --git a/src/main/java/com/mashibing/juc/c_001/T.java b/src/main/java/com/mashibing/juc/c_001/T.java index 16e8619..4812b22 100644 --- a/src/main/java/com/mashibing/juc/c_001/T.java +++ b/src/main/java/com/mashibing/juc/c_001/T.java @@ -1,6 +1,6 @@ /** - * synchronizedؼ - * ij + * synchronized关键字 + * 对某个对象加锁 * @author mashibing */ @@ -12,7 +12,7 @@ public class T { private Object o = new Object(); public void m() { - synchronized(o) { //κ߳ҪִĴ룬õo + synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁 count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } diff --git a/src/main/java/com/mashibing/juc/c_002/T.java b/src/main/java/com/mashibing/juc/c_002/T.java index 0bc6fa7..10a2a88 100644 --- a/src/main/java/com/mashibing/juc/c_002/T.java +++ b/src/main/java/com/mashibing/juc/c_002/T.java @@ -1,6 +1,6 @@ /** - * synchronizedؼ - * ij + * synchronized关键字 + * 对某个对象加锁 * @author mashibing */ @@ -11,7 +11,7 @@ public class T { private int count = 10; public void m() { - synchronized(this) { //κ߳ҪִĴ룬õthis + synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁 count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } diff --git a/src/main/java/com/mashibing/juc/c_003/T.java b/src/main/java/com/mashibing/juc/c_003/T.java index ba3cdcf..c126a1d 100644 --- a/src/main/java/com/mashibing/juc/c_003/T.java +++ b/src/main/java/com/mashibing/juc/c_003/T.java @@ -1,6 +1,6 @@ /** - * synchronizedؼ - * ij + * synchronized关键字 + * 对某个对象加锁 * @author mashibing */ @@ -10,7 +10,7 @@ public class T { private int count = 10; - public synchronized void m() { //ͬڷĴִʱҪsynchronized(this) + public synchronized void m() { //等同于在方法的代码执行时要synchronized(this) count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } diff --git a/src/main/java/com/mashibing/juc/c_003/T1.java b/src/main/java/com/mashibing/juc/c_003/T1.java index 332aca1..533b697 100644 --- a/src/main/java/com/mashibing/juc/c_003/T1.java +++ b/src/main/java/com/mashibing/juc/c_003/T1.java @@ -1,6 +1,6 @@ /** - * synchronizedؼ - * ij + * synchronized关键字 + * 对某个对象加锁 * @author mashibing */ @@ -10,12 +10,12 @@ public class T1 { private int count = 10; - public synchronized void m() { //ͬڷĴִʱҪsynchronized(this) + public synchronized void m() { //等同于在方法的代码执行时要synchronized(this) count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } - public void n() { //ʱҪ + public void n() { //访问这个方法的时候不需要上锁 count++; } } diff --git a/src/main/java/com/mashibing/juc/c_004/T.java b/src/main/java/com/mashibing/juc/c_004/T.java index 2bb2462..35f8490 100644 --- a/src/main/java/com/mashibing/juc/c_004/T.java +++ b/src/main/java/com/mashibing/juc/c_004/T.java @@ -1,6 +1,6 @@ /** - * synchronizedؼ - * ij + * synchronized关键字 + * 对某个对象加锁 * @author mashibing */ @@ -10,13 +10,13 @@ public class T { private static int count = 10; - public synchronized static void m() { //ͬsynchronized(FineCoarseLock.class) + public synchronized static void m() { //这里等同于synchronized(FineCoarseLock.class) count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } public static void mm() { - synchronized(T.class) { //һдsynchronized(this)Ƿԣ + synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以? count --; } } diff --git a/src/main/java/com/mashibing/juc/c_005/T.java b/src/main/java/com/mashibing/juc/c_005/T.java index 194e364..f8540e5 100644 --- a/src/main/java/com/mashibing/juc/c_005/T.java +++ b/src/main/java/com/mashibing/juc/c_005/T.java @@ -1,5 +1,5 @@ /** - * һ + * 分析一下这个程序的输出 * @author mashibing */ diff --git a/src/main/java/com/mashibing/juc/c_006/T.java b/src/main/java/com/mashibing/juc/c_006/T.java index 6ad2bd5..bd7b584 100644 --- a/src/main/java/com/mashibing/juc/c_006/T.java +++ b/src/main/java/com/mashibing/juc/c_006/T.java @@ -1,5 +1,5 @@ /** - * ԱһС򣬷һ + * 对比上面一个小程序,分析一下这个程序的输出 * @author mashibing */ diff --git a/src/main/java/com/mashibing/juc/c_007/T.java b/src/main/java/com/mashibing/juc/c_007/T.java index 2816ff9..2852acf 100644 --- a/src/main/java/com/mashibing/juc/c_007/T.java +++ b/src/main/java/com/mashibing/juc/c_007/T.java @@ -1,5 +1,5 @@ /** - * ͬͷͬǷͬʱã + * 同步和非同步方法是否可以同时调用? * @author mashibing */ @@ -36,7 +36,7 @@ public static void main(String[] args) { new Thread(t::m2, "t2").start(); /* - //1.8֮ǰд + //1.8之前的写法 new Thread(new Runnable() { @Override diff --git a/src/main/java/com/mashibing/juc/c_008/Account.java b/src/main/java/com/mashibing/juc/c_008/Account.java index 9f511fc..e177363 100644 --- a/src/main/java/com/mashibing/juc/c_008/Account.java +++ b/src/main/java/com/mashibing/juc/c_008/Account.java @@ -1,10 +1,10 @@ /** - * ⣺ģ˻ - * ҵд - * ҵ - * вУ + * 面试题:模拟银行账户 + * 对业务写方法加锁 + * 对业务读方法不加锁 + * 这样行不行? * - * ײ⣨dirtyRead + * 容易产生脏读问题(dirtyRead) */ package com.mashibing.juc.c_008; diff --git a/src/main/java/com/mashibing/juc/c_009/T.java b/src/main/java/com/mashibing/juc/c_009/T.java index 353b609..cdc8f50 100644 --- a/src/main/java/com/mashibing/juc/c_009/T.java +++ b/src/main/java/com/mashibing/juc/c_009/T.java @@ -1,6 +1,6 @@ /** - * һͬԵһͬһ߳ѾӵijٴʱȻõö. - * Ҳ˵synchronizedõǿ + * 一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁. + * 也就是说synchronized获得的锁是可重入的 * @author mashibing */ package com.mashibing.juc.c_009; diff --git a/src/main/java/com/mashibing/juc/c_010/T.java b/src/main/java/com/mashibing/juc/c_010/T.java index da981f6..067fedc 100644 --- a/src/main/java/com/mashibing/juc/c_010/T.java +++ b/src/main/java/com/mashibing/juc/c_010/T.java @@ -1,7 +1,7 @@ /** - * һͬԵһͬһ߳ѾӵijٴʱȻõö. - * Ҳ˵synchronizedõǿ - * Ǽ̳пܷΣøͬ + * 一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁. + * 也就是说synchronized获得的锁是可重入的 + * 这里是继承中有可能发生的情形,子类调用父类的同步方法 * @author mashibing */ package com.mashibing.juc.c_010; diff --git a/src/main/java/com/mashibing/juc/c_011/T.java b/src/main/java/com/mashibing/juc/c_011/T.java index 5328a16..f5ed6c6 100644 --- a/src/main/java/com/mashibing/juc/c_011/T.java +++ b/src/main/java/com/mashibing/juc/c_011/T.java @@ -1,9 +1,9 @@ /** - * 程序在执行过程中,如果出现异常,默认情况锁会被释放 - * 所以,在并发处理的过程中,有异常要多加小心,不然可能会发生不一致的情况。 - * 比如,在一个web app处理过程中,多个servlet线程共同访问同一个资源,这时如果异常处理不合适, - * 在第一个线程中抛出异常,其他线程就会进入同步代码区,有可能会访问到异常产生时的数据。 - * 因此要非常小心的处理同步业务逻辑中的异常 + * 绋嬪簭鍦ㄦ墽琛岃繃绋嬩腑锛屽鏋滃嚭鐜板紓甯革紝榛樿鎯呭喌閿佷細琚噴鏀� + * 鎵�浠ワ紝鍦ㄥ苟鍙戝鐞嗙殑杩囩▼涓紝鏈夊紓甯歌澶氬姞灏忓績锛屼笉鐒跺彲鑳戒細鍙戠敓涓嶄竴鑷寸殑鎯呭喌銆� + * 姣斿锛屽湪涓�涓獁eb app澶勭悊杩囩▼涓紝澶氫釜servlet绾跨▼鍏卞悓璁块棶鍚屼竴涓祫婧愶紝杩欐椂濡傛灉寮傚父澶勭悊涓嶅悎閫傦紝 + * 鍦ㄧ涓�涓嚎绋嬩腑鎶涘嚭寮傚父锛屽叾浠栫嚎绋嬪氨浼氳繘鍏ュ悓姝ヤ唬鐮佸尯锛屾湁鍙兘浼氳闂埌寮傚父浜х敓鏃剁殑鏁版嵁銆� + * 鍥犳瑕侀潪甯稿皬蹇冪殑澶勭悊鍚屾涓氬姟閫昏緫涓殑寮傚父 * @author mashibing */ package com.mashibing.juc.c_011; @@ -25,7 +25,7 @@ synchronized void m() { } if(count == 5) { - int i = 1/0; //此处抛出异常,锁将被释放,要想不被释放,可以在这里进行catch,然后让循环继续 + int i = 1/0; //姝ゅ鎶涘嚭寮傚父锛岄攣灏嗚閲婃斁锛岃鎯充笉琚噴鏀撅紝鍙互鍦ㄨ繖閲岃繘琛宑atch锛岀劧鍚庤寰幆缁х画 System.out.println(i); } } diff --git a/src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java b/src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java index 6b6883a..9639b4d 100644 --- a/src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java +++ b/src/main/java/com/mashibing/juc/c_012_Volatile/T01_HelloVolatile.java @@ -1,18 +1,18 @@ /** - * volatile ؼ֣ʹһڶ̼߳ɼ - * A B̶߳õһjavaĬA߳бһcopyB߳޸˸ñA߳δ֪ - * ʹvolatileؼ̶֣߳޸ֵ + * volatile 关键字,使一个变量在多个线程间可见 + * A B线程都用到一个变量,java默认是A线程中保留一份copy,这样如果B线程修改了该变量,则A线程未必知道 + * 使用volatile关键字,会让所有线程都会读到变量的修改值 * - * ĴУrunningǴڶڴt - * ߳t1ʼеʱ򣬻runningֵڴжt1̵߳Ĺйֱʹcopyÿζȥ - * ȡڴ棬߳޸runningֵ֮t1̸֪߳Բֹͣ + * 在下面的代码中,running是存在于堆内存的t对象中 + * 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个copy,并不会每次都去 + * 读取堆内存,这样,当主线程修改running的值之后,t1线程感知不到,所以不会停止运行 * - * ʹvolatileǿ̶߳ȥڴжȡrunningֵ + * 使用volatile,将会强制所有线程都去堆内存中读取running的值 * - * Ķƪ½и + * 可以阅读这篇文章进行更深入的理解 * http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html * - * volatileܱ֤̹߳ͬ޸runningʱIJһ⣬Ҳ˵volatilesynchronized + * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized * @author mashibing */ package com.mashibing.juc.c_012_Volatile; @@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit; public class T01_HelloVolatile { - /*volatile*/ boolean running = true; //Աһvolatile£н + /*volatile*/ boolean running = true; //对比一下有无volatile的情况下,整个程序运行结果的区别 void m() { System.out.println("m start"); while(running) { diff --git a/src/main/java/com/mashibing/juc/c_012_Volatile/T02_VolatileReference1.java b/src/main/java/com/mashibing/juc/c_012_Volatile/T02_VolatileReference1.java index eee70ed..a111606 100644 --- a/src/main/java/com/mashibing/juc/c_012_Volatile/T02_VolatileReference1.java +++ b/src/main/java/com/mashibing/juc/c_012_Volatile/T02_VolatileReference1.java @@ -1,5 +1,5 @@ /** - * volatile 引用类型(包括数组)只能保证引用本身的可见性,不能保证内部字段的可见性 + * volatile 寮曠敤绫诲瀷锛堝寘鎷暟缁勶級鍙兘淇濊瘉寮曠敤鏈韩鐨勫彲瑙佹�э紝涓嶈兘淇濊瘉鍐呴儴瀛楁鐨勫彲瑙佹�� */ package com.mashibing.juc.c_012_Volatile; @@ -28,7 +28,7 @@ void m() { public static void main(String[] args) { new Thread(T::m, "t1").start(); - //lambda表达式 new Thread(new Runnable( run() {m()} + //lambda琛ㄨ揪寮� new Thread(new Runnable( run() {m()} try { TimeUnit.SECONDS.sleep(1); diff --git a/src/main/java/com/mashibing/juc/c_012_Volatile/T03________VolatileReference2.java b/src/main/java/com/mashibing/juc/c_012_Volatile/T03________VolatileReference2.java index 33a4d24..31e440a 100644 --- a/src/main/java/com/mashibing/juc/c_012_Volatile/T03________VolatileReference2.java +++ b/src/main/java/com/mashibing/juc/c_012_Volatile/T03________VolatileReference2.java @@ -1,5 +1,5 @@ /** - * volatile 引用类型(包括数组)只能保证引用本身的可见性,不能保证内部字段的可见性 + * volatile 寮曠敤绫诲瀷锛堝寘鎷暟缁勶級鍙兘淇濊瘉寮曠敤鏈韩鐨勫彲瑙佹�э紝涓嶈兘淇濊瘉鍐呴儴瀛楁鐨勫彲瑙佹�� */ package com.mashibing.juc.c_012_Volatile; diff --git a/src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java b/src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java index ce4e07a..cdc7e82 100644 --- a/src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java +++ b/src/main/java/com/mashibing/juc/c_012_Volatile/T04_VolatileNotSync.java @@ -1,6 +1,6 @@ /** - * volatileܱ֤̹߳ͬ޸runningʱIJһ⣬Ҳ˵volatilesynchronized - * ij򣬲 + * volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized + * 运行下面的程序,并分析结果 * @author mashibing */ package com.mashibing.juc.c_012_Volatile; diff --git a/src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java b/src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java index ac28744..6a0d21c 100644 --- a/src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java +++ b/src/main/java/com/mashibing/juc/c_012_Volatile/T05_VolatileVsSync.java @@ -1,5 +1,5 @@ /** - * Աһ򣬿synchronizedsynchronizedԱ֤ɼԺԭԣvolatileֻܱ֤ɼ + * 对比上一个程序,可以用synchronized解决,synchronized可以保证可见性和原子性,volatile只能保证可见性 * @author mashibing */ package com.mashibing.juc.c_012_Volatile; diff --git a/src/main/java/com/mashibing/juc/c_016_LockOptimization/FineCoarseLock.java b/src/main/java/com/mashibing/juc/c_016_LockOptimization/FineCoarseLock.java index 8385a73..b2e76bc 100644 --- a/src/main/java/com/mashibing/juc/c_016_LockOptimization/FineCoarseLock.java +++ b/src/main/java/com/mashibing/juc/c_016_LockOptimization/FineCoarseLock.java @@ -1,7 +1,7 @@ /** - * synchronized优化 - * 同步代码块中的语句越少越好 - * 比较m1和m2 + * synchronized浼樺寲 + * 鍚屾浠g爜鍧椾腑鐨勮鍙ヨ秺灏戣秺濂� + * 姣旇緝m1鍜宮2 * @author mashibing */ package com.mashibing.juc.c_016_LockOptimization; @@ -20,7 +20,7 @@ synchronized void m1() { } catch (InterruptedException e) { e.printStackTrace(); } - //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 + //涓氬姟閫昏緫涓彧鏈変笅闈㈣繖鍙ラ渶瑕乻ync锛岃繖鏃朵笉搴旇缁欐暣涓柟娉曚笂閿� count ++; //do sth need not sync @@ -38,8 +38,8 @@ void m2() { } catch (InterruptedException e) { e.printStackTrace(); } - //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 - //采用细粒度的锁,可以使线程争用时间变短,从而提高效率 + //涓氬姟閫昏緫涓彧鏈変笅闈㈣繖鍙ラ渶瑕乻ync锛岃繖鏃朵笉搴旇缁欐暣涓柟娉曚笂閿� + //閲囩敤缁嗙矑搴︾殑閿侊紝鍙互浣跨嚎绋嬩簤鐢ㄦ椂闂村彉鐭紝浠庤�屾彁楂樻晥鐜� synchronized(this) { count ++; } diff --git a/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java b/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java index 4b7012e..cba6e16 100644 --- a/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java +++ b/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/DoNotLockString.java @@ -1,9 +1,9 @@ /** - * ҪַΪ - * Уm1m2ʵͬһ - * ᷢȽϹ󣬱õһ⣬ڸдַHello - * Դ룬ԼĴҲ"Hello",ʱпܷdz - * Ϊijõⲻʹͬһ + * 不要以字符串常量作为锁定对象 + * 在下面的例子中,m1和m2其实锁定的是同一个对象 + * 这种情况还会发生比较诡异的现象,比如你用到了一个类库,在该类库中代码锁定了字符串“Hello”, + * 但是你读不到源码,所以你在自己的代码中也锁定了"Hello",这时候就有可能发生非常诡异的死锁阻塞, + * 因为你的程序和你用到的类库不经意间使用了同一把锁 * * jetty * diff --git a/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java b/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java index 6e06d41..d43ec0b 100644 --- a/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java +++ b/src/main/java/com/mashibing/juc/c_017_MoreAboutSync/SyncSameObject.java @@ -1,7 +1,7 @@ /** - * ijooԷı䣬Ӱʹ - * oһĶı - * Ӧñ⽫ñĶ + * 锁定某对象o,如果o的属性发生改变,不影响锁的使用 + * 但是如果o变成另外一个对象,则锁定的对象发生改变 + * 应该避免将锁定对象的引用变成另外的对象 * @author mashibing */ package com.mashibing.juc.c_017_MoreAboutSync; @@ -30,7 +30,7 @@ void m() { public static void main(String[] args) { SyncSameObject t = new SyncSameObject(); - //һ߳ + //启动第一个线程 new Thread(t::m, "t1").start(); try { @@ -38,10 +38,10 @@ public static void main(String[] args) { } catch (InterruptedException e) { e.printStackTrace(); } - //ڶ߳ + //创建第二个线程 Thread t2 = new Thread(t::m, "t2"); - t.o = new Object(); //ı䣬t2̵ִ߳Уע͵仰߳2Զòִл + t.o = new Object(); //锁对象发生改变,所以t2线程得以执行,如果注释掉这句话,线程2将永远得不到执行机会 t2.start(); diff --git a/src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java b/src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java index c0bd5c0..dce2b7c 100644 --- a/src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java +++ b/src/main/java/com/mashibing/juc/c_018_00_AtomicXXX/T01_AtomicInteger.java @@ -1,6 +1,6 @@ /** - * ͬĸЧķʹAtomXXX - * AtomXXX౾ԭԵģܱ֤ԭԵ + * 解决同样的问题的更高效的方法,使用AtomXXX类 + * AtomXXX类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的 * @author mashibing */ package com.mashibing.juc.c_018_00_AtomicXXX; diff --git a/src/main/java/com/mashibing/juc/c_020/T01_ReentrantLock1.java b/src/main/java/com/mashibing/juc/c_020/T01_ReentrantLock1.java index ddee6f0..d36b9fe 100644 --- a/src/main/java/com/mashibing/juc/c_020/T01_ReentrantLock1.java +++ b/src/main/java/com/mashibing/juc/c_020/T01_ReentrantLock1.java @@ -1,7 +1,7 @@ /** - * reentrantlocksynchronized - * m1this,ֻm1ִϵʱ,m2ִ - * Ǹϰsynchronizedԭʼ + * reentrantlock用于替代synchronized + * 本例中由于m1锁定this,只有m1执行完毕的时候,m2才能执行 + * 这里是复习synchronized最原始的语义 * @author mashibing */ package com.mashibing.juc.c_020; diff --git a/src/main/java/com/mashibing/juc/c_020/T02_ReentrantLock2.java b/src/main/java/com/mashibing/juc/c_020/T02_ReentrantLock2.java index b6fb4ab..8d7e807 100644 --- a/src/main/java/com/mashibing/juc/c_020/T02_ReentrantLock2.java +++ b/src/main/java/com/mashibing/juc/c_020/T02_ReentrantLock2.java @@ -1,11 +1,11 @@ /** - * reentrantlocksynchronized - * m1this,ֻm1ִϵʱ,m2ִ - * Ǹϰsynchronizedԭʼ + * reentrantlock用于替代synchronized + * 由于m1锁定this,只有m1执行完毕的时候,m2才能执行 + * 这里是复习synchronized最原始的语义 * - * ʹreentrantlockͬĹ - * ҪעǣҪҪҪֶͷҪ˵飩 - * ʹsynĻ쳣jvmԶͷlockֶͷ˾finallyнͷ + * 使用reentrantlock可以完成同样的功能 + * 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍) + * 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放 * @author mashibing */ package com.mashibing.juc.c_020; diff --git a/src/main/java/com/mashibing/juc/c_020/T03_ReentrantLock3.java b/src/main/java/com/mashibing/juc/c_020/T03_ReentrantLock3.java index 268d93e..14f1085 100644 --- a/src/main/java/com/mashibing/juc/c_020/T03_ReentrantLock3.java +++ b/src/main/java/com/mashibing/juc/c_020/T03_ReentrantLock3.java @@ -1,13 +1,13 @@ /** - * reentrantlocksynchronized - * m1this,ֻm1ִϵʱ,m2ִ - * Ǹϰsynchronizedԭʼ + * reentrantlock用于替代synchronized + * 由于m1锁定this,只有m1执行完毕的时候,m2才能执行 + * 这里是复习synchronized最原始的语义 * - * ʹreentrantlockͬĹ - * ҪעǣҪҪҪֶͷҪ˵飩 - * ʹsynĻ쳣jvmԶͷlockֶͷ˾finallyнͷ + * 使用reentrantlock可以完成同样的功能 + * 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍) + * 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放 * - * ʹreentrantlockԽСtryLock޷ָʱ޷߳̿ԾǷȴ + * 使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待 * @author mashibing */ package com.mashibing.juc.c_020; @@ -35,9 +35,9 @@ void m1() { } /** - * ʹtryLockг񣬷ִ - * ԸtryLockķֵжǷ - * ҲָtryLockʱ䣬tryLock(time)׳쳣ҪעunclockĴŵfinally + * 使用tryLock进行尝试锁定,不管锁定与否,方法都将继续执行 + * 可以根据tryLock的返回值来判定是否锁定 + * 也可以指定tryLock的时间,由于tryLock(time)抛出异常,所以要注意unclock的处理,必须放到finally中 */ void m2() { /* diff --git a/src/main/java/com/mashibing/juc/c_020/T04_ReentrantLock4.java b/src/main/java/com/mashibing/juc/c_020/T04_ReentrantLock4.java index 8dad1c0..1a33800 100644 --- a/src/main/java/com/mashibing/juc/c_020/T04_ReentrantLock4.java +++ b/src/main/java/com/mashibing/juc/c_020/T04_ReentrantLock4.java @@ -1,16 +1,16 @@ /** - * reentrantlocksynchronized - * m1this,ֻm1ִϵʱ,m2ִ - * Ǹϰsynchronizedԭʼ + * reentrantlock用于替代synchronized + * 由于m1锁定this,只有m1执行完毕的时候,m2才能执行 + * 这里是复习synchronized最原始的语义 * - * ʹreentrantlockͬĹ - * ҪעǣҪҪҪֶͷҪ˵飩 - * ʹsynĻ쳣jvmԶͷlockֶͷ˾finallyнͷ + * 使用reentrantlock可以完成同样的功能 + * 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍) + * 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放 * - * ʹreentrantlockԽСtryLock޷ָʱ޷߳̿ԾǷȴ + * 使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待 * - * ʹReentrantLockԵlockInterruptiblyԶ߳interruptӦ - * һ̵߳ȴĹУԱ + * 使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应, + * 在一个线程等待锁的过程中,可以被打断 * * @author mashibing */ @@ -44,7 +44,7 @@ public static void main(String[] args) { Thread t2 = new Thread(()->{ try { //lock.lock(); - lock.lockInterruptibly(); //Զinterrupt()Ӧ + lock.lockInterruptibly(); //可以对interrupt()方法做出响应 System.out.println("t2 start"); TimeUnit.SECONDS.sleep(5); System.out.println("t2 end"); @@ -61,7 +61,7 @@ public static void main(String[] args) { } catch (InterruptedException e) { e.printStackTrace(); } - t2.interrupt(); //߳2ĵȴ + t2.interrupt(); //打断线程2的等待 } } diff --git a/src/main/java/com/mashibing/juc/c_020/T05_ReentrantLock5.java b/src/main/java/com/mashibing/juc/c_020/T05_ReentrantLock5.java index 79888fe..a2d668b 100644 --- a/src/main/java/com/mashibing/juc/c_020/T05_ReentrantLock5.java +++ b/src/main/java/com/mashibing/juc/c_020/T05_ReentrantLock5.java @@ -1,18 +1,18 @@ /** - * reentrantlocksynchronized - * m1this,ֻm1ִϵʱ,m2ִ - * Ǹϰsynchronizedԭʼ + * reentrantlock用于替代synchronized + * 由于m1锁定this,只有m1执行完毕的时候,m2才能执行 + * 这里是复习synchronized最原始的语义 * - * ʹreentrantlockͬĹ - * ҪעǣҪҪҪֶͷҪ˵飩 - * ʹsynĻ쳣jvmԶͷlockֶͷ˾finallyнͷ + * 使用reentrantlock可以完成同样的功能 + * 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍) + * 使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放 * - * ʹreentrantlockԽСtryLock޷ָʱ޷߳̿ԾǷȴ + * 使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待 * - * ʹReentrantLockԵlockInterruptiblyԶ߳interruptӦ - * һ̵߳ȴĹУԱ + * 使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应, + * 在一个线程等待锁的过程中,可以被打断 * - * ReentrantLockָΪƽ + * ReentrantLock还可以指定为公平锁 * * @author mashibing */ @@ -22,12 +22,12 @@ public class T05_ReentrantLock5 extends Thread { - private static ReentrantLock lock=new ReentrantLock(true); //ΪtrueʾΪƽԱ + private static ReentrantLock lock=new ReentrantLock(true); //参数为true表示为公平锁,请对比输出结果 public void run() { for(int i=0; i<100; i++) { lock.lock(); try{ - System.out.println(Thread.currentThread().getName()+""); + System.out.println(Thread.currentThread().getName()+"获得锁"); }finally{ lock.unlock(); } diff --git a/src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java b/src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java index 1dcfe93..af9216f 100644 --- a/src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java +++ b/src/main/java/com/mashibing/juc/c_020/T07_TestCyclicBarrier.java @@ -7,12 +7,12 @@ public class T07_TestCyclicBarrier { public static void main(String[] args) { //CyclicBarrier barrier = new CyclicBarrier(20); - CyclicBarrier barrier = new CyclicBarrier(20, () -> System.out.println("")); + CyclicBarrier barrier = new CyclicBarrier(20, () -> System.out.println("满人")); /*CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() { @Override public void run() { - System.out.println("ˣ"); + System.out.println("满人,发车"); } });*/ diff --git a/src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java b/src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java index 36788c5..944a0dc 100644 --- a/src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java +++ b/src/main/java/com/mashibing/juc/c_020/T08_TestPhaser.java @@ -45,14 +45,14 @@ protected boolean onAdvance(int phase, int registeredParties) { switch (phase) { case 0: - System.out.println("˵ˣ"); + System.out.println("所有人到齐了!"); return false; case 1: - System.out.println("˳ˣ"); + System.out.println("所有人吃完了!"); return false; case 2: - System.out.println("뿪ˣ"); - System.out.println(""); + System.out.println("所有人离开了!"); + System.out.println("婚礼结束!"); return true; default: return true; @@ -70,17 +70,17 @@ public Person(String name) { public void arrive() { milliSleep(r.nextInt(1000)); - System.out.printf("%s ֳ\n", name); + System.out.printf("%s 到达现场!\n", name); } public void eat() { milliSleep(r.nextInt(1000)); - System.out.printf("%s !\n", name); + System.out.printf("%s 吃完!\n", name); } public void leave() { milliSleep(r.nextInt(1000)); - System.out.printf("%s 뿪\n", name); + System.out.printf("%s 离开!\n", name); } } diff --git a/src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java b/src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java index 4e0d2f3..0d54c7a 100644 --- a/src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java +++ b/src/main/java/com/mashibing/juc/c_020/T09_TestPhaser2.java @@ -26,8 +26,8 @@ public static void main(String[] args) { new Thread(new Person("p" + i)).start(); } - new Thread(new Person("")).start(); - new Thread(new Person("")).start(); + new Thread(new Person("新郎")).start(); + new Thread(new Person("新娘")).start(); } @@ -39,19 +39,19 @@ protected boolean onAdvance(int phase, int registeredParties) { switch (phase) { case 0: - System.out.println("˵ˣ" + registeredParties); + System.out.println("所有人到齐了!" + registeredParties); System.out.println(); return false; case 1: - System.out.println("˳ˣ" + registeredParties); + System.out.println("所有人吃完了!" + registeredParties); System.out.println(); return false; case 2: - System.out.println("뿪ˣ" + registeredParties); + System.out.println("所有人离开了!" + registeredParties); System.out.println(); return false; case 3: - System.out.println("ﱧ" + registeredParties); + System.out.println("婚礼结束!新郎新娘抱抱!" + registeredParties); return true; default: return true; @@ -70,28 +70,28 @@ public Person(String name) { public void arrive() { milliSleep(r.nextInt(1000)); - System.out.printf("%s ֳ\n", name); + System.out.printf("%s 到达现场!\n", name); phaser.arriveAndAwaitAdvance(); } public void eat() { milliSleep(r.nextInt(1000)); - System.out.printf("%s !\n", name); + System.out.printf("%s 吃完!\n", name); phaser.arriveAndAwaitAdvance(); } public void leave() { milliSleep(r.nextInt(1000)); - System.out.printf("%s 뿪\n", name); + System.out.printf("%s 离开!\n", name); phaser.arriveAndAwaitAdvance(); } private void hug() { - if(name.equals("") || name.equals("")) { + if(name.equals("新郎") || name.equals("新娘")) { milliSleep(r.nextInt(1000)); - System.out.printf("%s \n", name); + System.out.printf("%s 洞房!\n", name); phaser.arriveAndAwaitAdvance(); } else { phaser.arriveAndDeregister(); diff --git a/src/main/java/com/mashibing/juc/c_020/T10_TestReadWriteLock.java b/src/main/java/com/mashibing/juc/c_020/T10_TestReadWriteLock.java index 6ce8769..87b2111 100644 --- a/src/main/java/com/mashibing/juc/c_020/T10_TestReadWriteLock.java +++ b/src/main/java/com/mashibing/juc/c_020/T10_TestReadWriteLock.java @@ -20,7 +20,7 @@ public static void read(Lock lock) { lock.lock(); Thread.sleep(1000); System.out.println("read over!"); - //模拟读取操作 + //妯℃嫙璇诲彇鎿嶄綔 } catch (InterruptedException e) { e.printStackTrace(); } finally { @@ -34,7 +34,7 @@ public static void write(Lock lock, int v) { Thread.sleep(1000); value = v; System.out.println("write over!"); - //模拟写操作 + //妯℃嫙鍐欐搷浣� } catch (InterruptedException e) { e.printStackTrace(); } finally { diff --git a/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java b/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java index f93f84d..686a306 100644 --- a/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java +++ b/src/main/java/com/mashibing/juc/c_020/T11_TestSemaphore.java @@ -6,7 +6,7 @@ public class T11_TestSemaphore { public static void main(String[] args) { //Semaphore s = new Semaphore(2); Semaphore s = new Semaphore(2, true); - //允许一个线程同时执行 + //鍏佽涓�涓嚎绋嬪悓鏃舵墽琛� //Semaphore s = new Semaphore(1); new Thread(()->{ diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java index 3204c3d..ee3262d 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T01_WithoutVolatile.java @@ -1,9 +1,9 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * + * 分析下面这个程序,能完成这个功能吗? * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -47,7 +47,7 @@ public static void main(String[] args) { break; } } - System.out.println("t2 "); + System.out.println("t2 结束"); }, "t2").start(); } } diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java index 85ea30c..381ff15 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T02_WithVolatile.java @@ -1,11 +1,11 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭ - * ңif break֮䱻̴߳ϣõĽҲȷ - * ôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环, + * 而且,如果在if 和 break之间被别的线程打断,得到的结果也不精确, + * 该怎么做呢? * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -18,7 +18,7 @@ public class T02_WithVolatile { - //volatileʹt2ܹõ֪ͨ + //添加volatile,使t2能够得到通知 //volatile List lists = new LinkedList(); volatile List lists = Collections.synchronizedList(new LinkedList<>()); @@ -52,7 +52,7 @@ public static void main(String[] args) { break; } } - System.out.println("t2 "); + System.out.println("t2 结束"); }, "t2").start(); } } diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java index fa455c0..44c8cbb 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T03_NotifyHoldingLock.java @@ -1,16 +1,16 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环,该怎么做呢? * - * ʹwaitnotifywaitͷnotifyͷ - * ҪעǣַҪ֤t2ִУҲt2ſ + * 这里使用wait和notify做到,wait会释放锁,而notify不会释放锁 + * 需要注意的是,运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以 * - * Ķij򣬲 - * Զsize=5ʱt2˳t1ʱt2Žյ֪ͨ˳ - * Ϊʲô + * 阅读下面的程序,并分析输出结果 + * 可以读到输出结果并不是size=5时t2退出,而是t1结束时t2才接收到通知而退出 + * 想想这是为什么? * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -22,7 +22,7 @@ public class T03_NotifyHoldingLock { //wait notify - //volatileʹt2ܹõ֪ͨ + //添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -40,7 +40,7 @@ public static void main(String[] args) { new Thread(() -> { synchronized(lock) { - System.out.println("t2"); + System.out.println("t2启动"); if(c.size() != 5) { try { lock.wait(); @@ -48,7 +48,7 @@ public static void main(String[] args) { e.printStackTrace(); } } - System.out.println("t2 "); + System.out.println("t2 结束"); } }, "t2").start(); @@ -60,7 +60,7 @@ public static void main(String[] args) { } new Thread(() -> { - System.out.println("t1"); + System.out.println("t1启动"); synchronized(lock) { for(int i=0; i<10; i++) { c.add(new Object()); diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java index 39abfba..4d4dd44 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T04_NotifyFreeLock.java @@ -1,19 +1,19 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环,该怎么做呢? * - * ʹwaitnotifywaitͷnotifyͷ - * ҪעǣַҪ֤t2ִУҲt2ſ + * 这里使用wait和notify做到,wait会释放锁,而notify不会释放锁 + * 需要注意的是,运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以 * - * Ķij򣬲 - * Զsize=5ʱt2˳t1ʱt2Žյ֪ͨ˳ - * Ϊʲô + * 阅读下面的程序,并分析输出结果 + * 可以读到输出结果并不是size=5时t2退出,而是t1结束时t2才接收到通知而退出 + * 想想这是为什么? * - * notify֮t1ͷt2˳Ҳnotify֪ͨt1ִ - * ͨẔ́ȽϷ + * notify之后,t1必须释放锁,t2退出后,也必须notify,通知t1继续执行 + * 整个通信过程比较繁琐 * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -25,7 +25,7 @@ public class T04_NotifyFreeLock { - //volatileʹt2ܹõ֪ͨ + //添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -43,7 +43,7 @@ public static void main(String[] args) { new Thread(() -> { synchronized(lock) { - System.out.println("t2"); + System.out.println("t2启动"); if(c.size() != 5) { try { lock.wait(); @@ -51,8 +51,8 @@ public static void main(String[] args) { e.printStackTrace(); } } - System.out.println("t2 "); - //֪ͨt1ִ + System.out.println("t2 结束"); + //通知t1继续执行 lock.notify(); } @@ -65,7 +65,7 @@ public static void main(String[] args) { } new Thread(() -> { - System.out.println("t1"); + System.out.println("t1启动"); synchronized(lock) { for(int i=0; i<10; i++) { c.add(new Object()); @@ -73,7 +73,7 @@ public static void main(String[] args) { if(c.size() == 5) { lock.notify(); - //ͷt2ִ + //释放锁,让t2得以执行 try { lock.wait(); } catch (InterruptedException e) { diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java index c722db0..52c5da8 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T05_CountDownLatch.java @@ -1,26 +1,26 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环,该怎么做呢? * - * ʹwaitnotifywaitͷnotifyͷ - * ҪעǣַҪ֤t2ִУҲt2ſ + * 这里使用wait和notify做到,wait会释放锁,而notify不会释放锁 + * 需要注意的是,运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以 * - * Ķij򣬲 - * Զsize=5ʱt2˳t1ʱt2Žյ֪ͨ˳ - * Ϊʲô + * 阅读下面的程序,并分析输出结果 + * 可以读到输出结果并不是size=5时t2退出,而是t1结束时t2才接收到通知而退出 + * 想想这是为什么? * - * notify֮t1ͷt2˳Ҳnotify֪ͨt1ִ - * ͨẔ́ȽϷ + * notify之后,t1必须释放锁,t2退出后,也必须notify,通知t1继续执行 + * 整个通信过程比较繁琐 * - * ʹLatchţwait notify֪ͨ - * ôͨŷʽ򵥣ͬʱҲָȴʱ - * ʹawaitcountdownwaitnotify - * CountDownLatch漰countֵΪʱǰ̼߳ - * 漰ֻͬ漰߳ͨŵʱsynchronized + wait/notifyԵ̫ - * ʱӦÿcountdownlatch/cyclicbarrier/semaphore + * 使用Latch(门闩)替代wait notify来进行通知 + * 好处是通信方式简单,同时也可以指定等待时间 + * 使用await和countdown方法替代wait和notify + * CountDownLatch不涉及锁定,当count的值为零时当前线程继续运行 + * 当不涉及同步,只是涉及线程通信的时候,用synchronized + wait/notify就显得太重了 + * 这时应该考虑countdownlatch/cyclicbarrier/semaphore * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -32,7 +32,7 @@ public class T05_CountDownLatch { - // volatileʹt2ܹõ֪ͨ + // 添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -49,18 +49,18 @@ public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(1); new Thread(() -> { - System.out.println("t2"); + System.out.println("t2启动"); if (c.size() != 5) { try { latch.await(); - //Ҳָȴʱ + //也可以指定等待时间 //latch.await(5000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } - System.out.println("t2 "); + System.out.println("t2 结束"); }, "t2").start(); @@ -71,13 +71,13 @@ public static void main(String[] args) { } new Thread(() -> { - System.out.println("t1"); + System.out.println("t1启动"); for (int i = 0; i < 10; i++) { c.add(new Object()); System.out.println("add " + i); if (c.size() == 5) { - // ţt2ִ + // 打开门闩,让t2得以执行 latch.countDown(); } diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java index 6bf28c9..c398e89 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T06_LockSupport.java @@ -1,26 +1,26 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环,该怎么做呢? * - * ʹwaitnotifywaitͷnotifyͷ - * ҪעǣַҪ֤t2ִУҲt2ſ + * 这里使用wait和notify做到,wait会释放锁,而notify不会释放锁 + * 需要注意的是,运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以 * - * Ķij򣬲 - * Զsize=5ʱt2˳t1ʱt2Žյ֪ͨ˳ - * Ϊʲô + * 阅读下面的程序,并分析输出结果 + * 可以读到输出结果并不是size=5时t2退出,而是t1结束时t2才接收到通知而退出 + * 想想这是为什么? * - * notify֮t1ͷt2˳Ҳnotify֪ͨt1ִ - * ͨẔ́ȽϷ + * notify之后,t1必须释放锁,t2退出后,也必须notify,通知t1继续执行 + * 整个通信过程比较繁琐 * - * ʹLatchţwait notify֪ͨ - * ôͨŷʽ򵥣ͬʱҲָȴʱ - * ʹawaitcountdownwaitnotify - * CountDownLatch漰countֵΪʱǰ̼߳ - * 漰ֻͬ漰߳ͨŵʱsynchronized + wait/notifyԵ̫ - * ʱӦÿcountdownlatch/cyclicbarrier/semaphore + * 使用Latch(门闩)替代wait notify来进行通知 + * 好处是通信方式简单,同时也可以指定等待时间 + * 使用await和countdown方法替代wait和notify + * CountDownLatch不涉及锁定,当count的值为零时当前线程继续运行 + * 当不涉及同步,只是涉及线程通信的时候,用synchronized + wait/notify就显得太重了 + * 这时应该考虑countdownlatch/cyclicbarrier/semaphore * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -35,7 +35,7 @@ public class T06_LockSupport { - // volatileʹt2ܹõ֪ͨ + // 添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -52,13 +52,13 @@ public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(1); Thread t2 = new Thread(() -> { - System.out.println("t2"); + System.out.println("t2启动"); if (c.size() != 5) { LockSupport.park(); } - System.out.println("t2 "); + System.out.println("t2 结束"); }, "t2"); @@ -72,7 +72,7 @@ public static void main(String[] args) { } new Thread(() -> { - System.out.println("t1"); + System.out.println("t1启动"); for (int i = 0; i < 10; i++) { c.add(new Object()); System.out.println("add " + i); diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java index ade26aa..f044fe3 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T07_LockSupport_WithoutSleep.java @@ -1,26 +1,26 @@ /** - * ⣺Ա - * ʵһṩaddsize - * д̣߳߳110ԪصУ߳2ʵּԪصĸ5ʱ߳2ʾ + * 曾经的面试题:(淘宝?) + * 实现一个容器,提供两个方法,add,size + * 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束 * - * listsvolatile֮t2ܹӵ֪ͨǣt2̵߳ѭ˷cpuѭôأ + * 给lists添加volatile之后,t2能够接到通知,但是,t2线程的死循环很浪费cpu,如果不用死循环,该怎么做呢? * - * ʹwaitnotifywaitͷnotifyͷ - * ҪעǣַҪ֤t2ִУҲt2ſ + * 这里使用wait和notify做到,wait会释放锁,而notify不会释放锁 + * 需要注意的是,运用这种方法,必须要保证t2先执行,也就是首先让t2监听才可以 * - * Ķij򣬲 - * Զsize=5ʱt2˳t1ʱt2Žյ֪ͨ˳ - * Ϊʲô + * 阅读下面的程序,并分析输出结果 + * 可以读到输出结果并不是size=5时t2退出,而是t1结束时t2才接收到通知而退出 + * 想想这是为什么? * - * notify֮t1ͷt2˳Ҳnotify֪ͨt1ִ - * ͨẔ́ȽϷ + * notify之后,t1必须释放锁,t2退出后,也必须notify,通知t1继续执行 + * 整个通信过程比较繁琐 * - * ʹLatchţwait notify֪ͨ - * ôͨŷʽ򵥣ͬʱҲָȴʱ - * ʹawaitcountdownwaitnotify - * CountDownLatch漰countֵΪʱǰ̼߳ - * 漰ֻͬ漰߳ͨŵʱsynchronized + wait/notifyԵ̫ - * ʱӦÿcountdownlatch/cyclicbarrier/semaphore + * 使用Latch(门闩)替代wait notify来进行通知 + * 好处是通信方式简单,同时也可以指定等待时间 + * 使用await和countdown方法替代wait和notify + * CountDownLatch不涉及锁定,当count的值为零时当前线程继续运行 + * 当不涉及同步,只是涉及线程通信的时候,用synchronized + wait/notify就显得太重了 + * 这时应该考虑countdownlatch/cyclicbarrier/semaphore * @author mashibing */ package com.mashibing.juc.c_020_01_Interview; @@ -35,7 +35,7 @@ public class T07_LockSupport_WithoutSleep { - // volatileʹt2ܹõ֪ͨ + // 添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -52,7 +52,7 @@ public static void main(String[] args) { T07_LockSupport_WithoutSleep c = new T07_LockSupport_WithoutSleep(); t1 = new Thread(() -> { - System.out.println("t1"); + System.out.println("t1启动"); for (int i = 0; i < 10; i++) { c.add(new Object()); System.out.println("add " + i); @@ -65,13 +65,13 @@ public static void main(String[] args) { }, "t1"); t2 = new Thread(() -> { - //System.out.println("t2"); + //System.out.println("t2启动"); //if (c.size() != 5) { LockSupport.park(); //} - System.out.println("t2 "); + System.out.println("t2 结束"); LockSupport.unpark(t1); diff --git a/src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java b/src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java index 131d6a3..c39784b 100644 --- a/src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java +++ b/src/main/java/com/mashibing/juc/c_020_01_Interview/T08_Semaphore.java @@ -6,7 +6,7 @@ import java.util.concurrent.locks.LockSupport; public class T08_Semaphore { - // volatileʹt2ܹõ֪ͨ + // 添加volatile,使t2能够得到通知 volatile List lists = new ArrayList(); public void add(Object o) { @@ -59,7 +59,7 @@ public static void main(String[] args) { t2 = new Thread(() -> { try { s.acquire(); - System.out.println("t2 "); + System.out.println("t2 结束"); s.release(); } catch (InterruptedException e) { e.printStackTrace(); diff --git a/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java b/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java index baa5d2c..94bfb67 100644 --- a/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java +++ b/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer1.java @@ -1,8 +1,8 @@ /** - * ⣺дһ̶ͬӵputgetԼgetCount - * ܹ֧2߳Լ10̵߳ + * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, + * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 * - * ʹwaitnotify/notifyAllʵ + * 使用wait和notify/notifyAll来实现 * * @author mashibing */ @@ -13,12 +13,12 @@ public class MyContainer1 { final private LinkedList lists = new LinkedList<>(); - final private int MAX = 10; //10Ԫ + final private int MAX = 10; //最多10个元素 private int count = 0; public synchronized void put(T t) { - while(lists.size() == MAX) { //Ϊʲôwhileif + while(lists.size() == MAX) { //想想为什么用while而不是用if? try { this.wait(); //effective java } catch (InterruptedException e) { @@ -28,7 +28,7 @@ public synchronized void put(T t) { lists.add(t); ++count; - this.notifyAll(); //֪ͨ߳̽ + this.notifyAll(); //通知消费者线程进行消费 } public synchronized T get() { @@ -42,13 +42,13 @@ public synchronized T get() { } t = lists.removeFirst(); count --; - this.notifyAll(); //֪߽ͨ + this.notifyAll(); //通知生产者进行生产 return t; } public static void main(String[] args) { MyContainer1 c = new MyContainer1<>(); - //߳ + //启动消费者线程 for(int i=0; i<10; i++) { new Thread(()->{ for(int j=0; j<5; j++) System.out.println(c.get()); @@ -61,7 +61,7 @@ public static void main(String[] args) { e.printStackTrace(); } - //߳ + //启动生产者线程 for(int i=0; i<2; i++) { new Thread(()->{ for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j); diff --git a/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer2.java b/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer2.java index 54284d6..eaf4cfb 100644 --- a/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer2.java +++ b/src/main/java/com/mashibing/juc/c_021_01_interview/MyContainer2.java @@ -1,11 +1,11 @@ /** - * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法, - * 能够支持2个生产者线程以及10个消费者线程的阻塞调用 + * 闈㈣瘯棰橈細鍐欎竴涓浐瀹氬閲忓悓姝ュ鍣紝鎷ユ湁put鍜実et鏂规硶锛屼互鍙奼etCount鏂规硶锛� + * 鑳藉鏀寔2涓敓浜ц�呯嚎绋嬩互鍙�10涓秷璐硅�呯嚎绋嬬殑闃诲璋冪敤 * - * 使用wait和notify/notifyAll来实现 + * 浣跨敤wait鍜宯otify/notifyAll鏉ュ疄鐜� * - * 使用Lock和Condition来实现 - * 对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒 + * 浣跨敤Lock鍜孋ondition鏉ュ疄鐜� + * 瀵规瘮涓ょ鏂瑰紡锛孋ondition鐨勬柟寮忓彲浠ユ洿鍔犵簿纭殑鎸囧畾鍝簺绾跨▼琚敜閱� * * @author mashibing */ @@ -19,7 +19,7 @@ public class MyContainer2 { final private LinkedList lists = new LinkedList<>(); - final private int MAX = 10; //最多10个元素 + final private int MAX = 10; //鏈�澶�10涓厓绱� private int count = 0; private Lock lock = new ReentrantLock(); @@ -29,13 +29,13 @@ public class MyContainer2 { public void put(T t) { try { lock.lock(); - while(lists.size() == MAX) { //想想为什么用while而不是用if? + while(lists.size() == MAX) { //鎯虫兂涓轰粈涔堢敤while鑰屼笉鏄敤if锛� producer.await(); } lists.add(t); ++count; - consumer.signalAll(); //通知消费者线程进行消费 + consumer.signalAll(); //閫氱煡娑堣垂鑰呯嚎绋嬭繘琛屾秷璐� } catch (InterruptedException e) { e.printStackTrace(); } finally { @@ -52,7 +52,7 @@ public T get() { } t = lists.removeFirst(); count --; - producer.signalAll(); //通知生产者进行生产 + producer.signalAll(); //閫氱煡鐢熶骇鑰呰繘琛岀敓浜� } catch (InterruptedException e) { e.printStackTrace(); } finally { @@ -63,7 +63,7 @@ public T get() { public static void main(String[] args) { MyContainer2 c = new MyContainer2<>(); - //启动消费者线程 + //鍚姩娑堣垂鑰呯嚎绋� for(int i=0; i<10; i++) { new Thread(()->{ for(int j=0; j<5; j++) System.out.println(c.get()); @@ -76,7 +76,7 @@ public static void main(String[] args) { e.printStackTrace(); } - //启动生产者线程 + //鍚姩鐢熶骇鑰呯嚎绋� for(int i=0; i<2; i++) { new Thread(()->{ for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j); diff --git a/src/main/java/com/mashibing/juc/c_021_02_AQS/MLock.java b/src/main/java/com/mashibing/juc/c_021_02_AQS/MLock.java index b73f235..9bf52e9 100644 --- a/src/main/java/com/mashibing/juc/c_021_02_AQS/MLock.java +++ b/src/main/java/com/mashibing/juc/c_021_02_AQS/MLock.java @@ -1,6 +1,6 @@ /** - * 通过AQS实现自定义锁,目前仅实现了lock和unlock - * @author 马士兵 + * 閫氳繃AQS瀹炵幇鑷畾涔夐攣锛岀洰鍓嶄粎瀹炵幇浜唋ock鍜寀nlock + * @author 椹+鍏� */ package com.mashibing.juc.c_021_02_AQS; diff --git a/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java b/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java index bd3f655..3616144 100644 --- a/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java +++ b/src/main/java/com/mashibing/juc/c_021_02_AQS/TestReentrantLock.java @@ -15,6 +15,6 @@ public static void main(String[] args) { lock.unlock(); - //synchronized 程序员的丽春院 JUC + //synchronized 绋嬪簭鍛樼殑涓芥槬闄� JUC } } diff --git a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T02_SoftReference.java b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T02_SoftReference.java index 3b4bef9..f3d7d9a 100644 --- a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T02_SoftReference.java +++ b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T02_SoftReference.java @@ -1,8 +1,8 @@ /** - * 软引用 - * 软引用是用来描述一些还有用但并非必须的对象。 - * 对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。 - * 如果这次回收还没有足够的内存,才会抛出内存溢出异常。 + * 杞紩鐢� + * 杞紩鐢ㄦ槸鐢ㄦ潵鎻忚堪涓�浜涜繕鏈夌敤浣嗗苟闈炲繀椤荤殑瀵硅薄銆� + * 瀵逛簬杞紩鐢ㄥ叧鑱旂潃鐨勫璞★紝鍦ㄧ郴缁熷皢瑕佸彂鐢熷唴瀛樻孩鍑哄紓甯镐箣鍓嶏紝灏嗕細鎶婅繖浜涘璞″垪杩涘洖鏀惰寖鍥磋繘琛岀浜屾鍥炴敹銆� + * 濡傛灉杩欐鍥炴敹杩樻病鏈夎冻澶熺殑鍐呭瓨锛屾墠浼氭姏鍑哄唴瀛樻孩鍑哄紓甯搞�� * -Xmx20M */ package com.mashibing.juc.c_022_RefTypeAndThreadLocal; @@ -22,10 +22,10 @@ public static void main(String[] args) { } System.out.println(m.get()); - //再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉 + //鍐嶅垎閰嶄竴涓暟缁勶紝heap灏嗚涓嶄笅锛岃繖鏃跺�欑郴缁熶細鍨冨溇鍥炴敹锛屽厛鍥炴敹涓�娆★紝濡傛灉涓嶅锛屼細鎶婅蒋寮曠敤骞叉帀 byte[] b = new byte[1024*1024*15]; System.out.println(m.get()); } } -//软引用非常适合缓存使用 +//杞紩鐢ㄩ潪甯搁�傚悎缂撳瓨浣跨敤 diff --git a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T03_WeakReference.java b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T03_WeakReference.java index d049f61..a3c3839 100644 --- a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T03_WeakReference.java +++ b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T03_WeakReference.java @@ -1,5 +1,5 @@ /** - * 弱引用遭到gc就会回收 + * 寮卞紩鐢ㄩ伃鍒癵c灏变細鍥炴敹 * */ package com.mashibing.juc.c_022_RefTypeAndThreadLocal; diff --git a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T04_PhantomReference.java b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T04_PhantomReference.java index 0f7bd2f..4cd4d3a 100644 --- a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T04_PhantomReference.java +++ b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/T04_PhantomReference.java @@ -1,22 +1,22 @@ /** * * - * 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响, - * 也无法通过虚引用来获取一个对象的实例。 - * 为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。 - * 虚引用和弱引用对关联对象的回收都不会产生影响,如果只有虚引用活着弱引用关联着对象, - * 那么这个对象就会被回收。它们的不同之处在于弱引用的get方法,虚引用的get方法始终返回null, - * 弱引用可以使用ReferenceQueue,虚引用必须配合ReferenceQueue使用。 + * 涓�涓璞℃槸鍚︽湁铏氬紩鐢ㄧ殑瀛樺湪锛屽畬鍏ㄤ笉浼氬鍏剁敓瀛樻椂闂存瀯鎴愬奖鍝嶏紝 + * 涔熸棤娉曢�氳繃铏氬紩鐢ㄦ潵鑾峰彇涓�涓璞$殑瀹炰緥銆� + * 涓轰竴涓璞¤缃櫄寮曠敤鍏宠仈鐨勫敮涓�鐩殑灏辨槸鑳藉湪杩欎釜瀵硅薄琚敹闆嗗櫒鍥炴敹鏃舵敹鍒颁竴涓郴缁熼�氱煡銆� + * 铏氬紩鐢ㄥ拰寮卞紩鐢ㄥ鍏宠仈瀵硅薄鐨勫洖鏀堕兘涓嶄細浜х敓褰卞搷锛屽鏋滃彧鏈夎櫄寮曠敤娲荤潃寮卞紩鐢ㄥ叧鑱旂潃瀵硅薄锛� + * 閭d箞杩欎釜瀵硅薄灏变細琚洖鏀躲�傚畠浠殑涓嶅悓涔嬪鍦ㄤ簬寮卞紩鐢ㄧ殑get鏂规硶锛岃櫄寮曠敤鐨刧et鏂规硶濮嬬粓杩斿洖null, + * 寮卞紩鐢ㄥ彲浠ヤ娇鐢≧eferenceQueue,铏氬紩鐢ㄥ繀椤婚厤鍚圧eferenceQueue浣跨敤銆� * - * jdk中直接内存的回收就用到虚引用,由于jvm自动内存管理的范围是堆内存, - * 而直接内存是在堆内存之外(其实是内存映射文件,自行去理解虚拟内存空间的相关概念), - * 所以直接内存的分配和回收都是有Unsafe类去操作,java在申请一块直接内存之后, - * 会在堆内存分配一个对象保存这个堆外内存的引用, - * 这个对象被垃圾收集器管理,一旦这个对象被回收, - * 相应的用户线程会收到通知并对直接内存进行清理工作。 + * jdk涓洿鎺ュ唴瀛樼殑鍥炴敹灏辩敤鍒拌櫄寮曠敤锛岀敱浜巎vm鑷姩鍐呭瓨绠$悊鐨勮寖鍥存槸鍫嗗唴瀛橈紝 + * 鑰岀洿鎺ュ唴瀛樻槸鍦ㄥ爢鍐呭瓨涔嬪锛堝叾瀹炴槸鍐呭瓨鏄犲皠鏂囦欢锛岃嚜琛屽幓鐞嗚В铏氭嫙鍐呭瓨绌洪棿鐨勭浉鍏虫蹇碉級锛� + * 鎵�浠ョ洿鎺ュ唴瀛樼殑鍒嗛厤鍜屽洖鏀堕兘鏄湁Unsafe绫诲幓鎿嶄綔锛宩ava鍦ㄧ敵璇蜂竴鍧楃洿鎺ュ唴瀛樹箣鍚庯紝 + * 浼氬湪鍫嗗唴瀛樺垎閰嶄竴涓璞′繚瀛樿繖涓爢澶栧唴瀛樼殑寮曠敤锛� + * 杩欎釜瀵硅薄琚瀮鍦炬敹闆嗗櫒绠$悊锛屼竴鏃﹁繖涓璞¤鍥炴敹锛� + * 鐩稿簲鐨勭敤鎴风嚎绋嬩細鏀跺埌閫氱煡骞跺鐩存帴鍐呭瓨杩涜娓呯悊宸ヤ綔銆� * - * 事实上,虚引用有一个很重要的用途就是用来做堆外内存的释放, - * DirectByteBuffer就是通过虚引用来实现堆外内存的释放的。 + * 浜嬪疄涓婏紝铏氬紩鐢ㄦ湁涓�涓緢閲嶈鐨勭敤閫斿氨鏄敤鏉ュ仛鍫嗗鍐呭瓨鐨勯噴鏀撅紝 + * DirectByteBuffer灏辨槸閫氳繃铏氬紩鐢ㄦ潵瀹炵幇鍫嗗鍐呭瓨鐨勯噴鏀剧殑銆� * */ @@ -58,7 +58,7 @@ public static void main(String[] args) { while (true) { Reference poll = QUEUE.poll(); if (poll != null) { - System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll); + System.out.println("--- 铏氬紩鐢ㄥ璞¤jvm鍥炴敹浜� ---- " + poll); } } }).start(); diff --git a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java index e7879d0..8a8628b 100644 --- a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java +++ b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal1.java @@ -1,7 +1,7 @@ /** - * ThreadLocalֲ߳̾ + * ThreadLocal线程局部变量 * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_022_RefTypeAndThreadLocal; diff --git a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java index 84b0ac3..3d18cd7 100644 --- a/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java +++ b/src/main/java/com/mashibing/juc/c_022_RefTypeAndThreadLocal/ThreadLocal2.java @@ -1,12 +1,12 @@ /** - * ThreadLocalֲ߳̾ + * ThreadLocal线程局部变量 * - * ThreadLocalʹÿռ任ʱ䣬synchronizedʹʱ任ռ - * hibernatesessionʹThreadLocalУsynchronizedʹ + * ThreadLocal是使用空间换时间,synchronized是使用时间换空间 + * 比如在hibernate中session就存在与ThreadLocal中,避免synchronized的使用 * - * ijThreadLocal + * 运行下面的程序,理解ThreadLocal * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_022_RefTypeAndThreadLocal; diff --git a/src/main/java/com/mashibing/juc/c_023/Singleton.java b/src/main/java/com/mashibing/juc/c_023/Singleton.java index 0236172..bc77bad 100644 --- a/src/main/java/com/mashibing/juc/c_023/Singleton.java +++ b/src/main/java/com/mashibing/juc/c_023/Singleton.java @@ -1,11 +1,11 @@ /** - * 线程安全的单例模式: + * 绾跨▼瀹夊叏鐨勫崟渚嬫ā寮忥細 * - * 阅读文章:http://www.cnblogs.com/xudong-bupt/p/3433643.html + * 闃呰鏂囩珷锛歨ttp://www.cnblogs.com/xudong-bupt/p/3433643.html * - * 更好的是采用下面的方式,既不用加锁,也能实现懒加载 + * 鏇村ソ鐨勬槸閲囩敤涓嬮潰鐨勬柟寮忥紝鏃笉鐢ㄥ姞閿侊紝涔熻兘瀹炵幇鎳掑姞杞� * - * @author 马士兵 + * @author 椹+鍏� */ package com.mashibing.juc.c_023; diff --git a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java index 18f9dc8..98eae3b 100644 --- a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java +++ b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller1.java @@ -1,13 +1,13 @@ /** - * NŻƱÿƱһ - * ͬʱ10ڶƱ - * дһģ + * 有N张火车票,每张票都有一个编号 + * 同时有10个窗口对外售票 + * 请写一个模拟程序 * - * ijܻЩ⣿ - * ظۣۣ + * 分析下面的程序可能会产生哪些问题? + * 重复销售?超量销售? * * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_024_FromVectorToQueue; @@ -18,7 +18,7 @@ public class TicketSeller1 { static List tickets = new ArrayList<>(); static { - for(int i=0; i<10000; i++) tickets.add("Ʊţ" + i); + for(int i=0; i<10000; i++) tickets.add("票编号:" + i); } @@ -27,7 +27,7 @@ public static void main(String[] args) { for(int i=0; i<10; i++) { new Thread(()->{ while(tickets.size() > 0) { - System.out.println("--" + tickets.remove(0)); + System.out.println("销售了--" + tickets.remove(0)); } }).start(); } diff --git a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java index 98e26c7..89bcedb 100644 --- a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java +++ b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller2.java @@ -1,14 +1,14 @@ /** - * NŻƱÿƱһ - * ͬʱ10ڶƱ - * дһģ + * 有N张火车票,每张票都有一个编号 + * 同时有10个窗口对外售票 + * 请写一个模拟程序 * - * ijܻЩ⣿ + * 分析下面的程序可能会产生哪些问题? * - * ʹVectorCollections.synchronizedXXX - * һ£ܽ + * 使用Vector或者Collections.synchronizedXXX + * 分析一下,这样能解决问题吗? * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_024_FromVectorToQueue; @@ -20,7 +20,7 @@ public class TicketSeller2 { static { - for(int i=0; i<1000; i++) tickets.add("Ʊ ţ" + i); + for(int i=0; i<1000; i++) tickets.add("票 编号:" + i); } public static void main(String[] args) { @@ -36,7 +36,7 @@ public static void main(String[] args) { } - System.out.println("--" + tickets.remove(0)); + System.out.println("销售了--" + tickets.remove(0)); } }).start(); } diff --git a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java index 9de6de2..bcc19e7 100644 --- a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java +++ b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller3.java @@ -1,18 +1,18 @@ /** - * NŻƱÿƱһ - * ͬʱ10ڶƱ - * дһģ + * 有N张火车票,每张票都有一个编号 + * 同时有10个窗口对外售票 + * 请写一个模拟程序 * - * ijܻЩ⣿ - * ظۣۣ + * 分析下面的程序可能会产生哪些问题? + * 重复销售?超量销售? * - * ʹVectorCollections.synchronizedXXX - * һ£ܽ + * 使用Vector或者Collections.synchronizedXXX + * 分析一下,这样能解决问题吗? * - * ABͬģABɵĸϲҲδͬģȻҪԼͬ - * жsizeͽremoveһԭӲ + * 就算操作A和B都是同步的,但A和B组成的复合操作也未必是同步的,仍然需要自己进行同步 + * 就像这个程序,判断size和进行remove必须是一整个的原子操作 * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_024_FromVectorToQueue; @@ -25,7 +25,7 @@ public class TicketSeller3 { static { - for(int i=0; i<1000; i++) tickets.add("Ʊ ţ" + i); + for(int i=0; i<1000; i++) tickets.add("票 编号:" + i); } public static void main(String[] args) { @@ -42,7 +42,7 @@ public static void main(String[] args) { e.printStackTrace(); } - System.out.println("--" + tickets.remove(0)); + System.out.println("销售了--" + tickets.remove(0)); } } }).start(); diff --git a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java index ae97461..cd03f45 100644 --- a/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java +++ b/src/main/java/com/mashibing/juc/c_024_FromVectorToQueue/TicketSeller4.java @@ -1,20 +1,20 @@ /** - * NŻƱÿƱһ - * ͬʱ10ڶƱ - * дһģ + * 有N张火车票,每张票都有一个编号 + * 同时有10个窗口对外售票 + * 请写一个模拟程序 * - * ijܻЩ⣿ - * ظۣۣ + * 分析下面的程序可能会产生哪些问题? + * 重复销售?超量销售? * - * ʹVectorCollections.synchronizedXXX - * һ£ܽ + * 使用Vector或者Collections.synchronizedXXX + * 分析一下,这样能解决问题吗? * - * ABͬģABɵĸϲҲδͬģȻҪԼͬ - * жsizeͽremoveһԭӲ + * 就算操作A和B都是同步的,但A和B组成的复合操作也未必是同步的,仍然需要自己进行同步 + * 就像这个程序,判断size和进行remove必须是一整个的原子操作 * - * ʹConcurrentQueue߲ + * 使用ConcurrentQueue提高并发性 * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_024_FromVectorToQueue; @@ -26,7 +26,7 @@ public class TicketSeller4 { static { - for(int i=0; i<1000; i++) tickets.add("Ʊ ţ" + i); + for(int i=0; i<1000; i++) tickets.add("票 编号:" + i); } public static void main(String[] args) { @@ -36,7 +36,7 @@ public static void main(String[] args) { while(true) { String s = tickets.poll(); if(s == null) break; - else System.out.println("--" + s); + else System.out.println("销售了--" + s); } }).start(); } diff --git a/src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java b/src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java index 326186e..236836d 100644 --- a/src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java +++ b/src/main/java/com/mashibing/juc/c_025/T01_ConcurrentMap.java @@ -1,7 +1,7 @@ /** * http://blog.csdn.net/sunxianghuang/article/details/52221913 * http://www.educity.cn/java/498061.html - * Ķconcurrentskiplistmap + * 阅读concurrentskiplistmap */ package com.mashibing.juc.c_025; @@ -13,7 +13,7 @@ public class T01_ConcurrentMap { public static void main(String[] args) { Map map = new ConcurrentHashMap<>(); - //Map map = new ConcurrentSkipListMap<>(); //߲ + //Map map = new ConcurrentSkipListMap<>(); //高并发并且排序 //Map map = new Hashtable<>(); //Map map = new HashMap<>(); //Collections.synchronizedXXX diff --git a/src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java b/src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java index 5484cdf..3fe931d 100644 --- a/src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java +++ b/src/main/java/com/mashibing/juc/c_025/T02_CopyOnWriteList.java @@ -1,11 +1,11 @@ /** - * дʱ copy on write - * ̻߳£дʱЧʵͣʱЧʸ - * ʺдٶĻ + * 写时复制容器 copy on write + * 多线程环境下,写时效率低,读时效率高 + * 适合写少读多的环境 * * * - * @author ʿ + * @author 马士兵 */ package com.mashibing.juc.c_025; @@ -19,7 +19,7 @@ public class T02_CopyOnWriteList { public static void main(String[] args) { List lists = - //new ArrayList<>(); //⣡ + //new ArrayList<>(); //这个会出并发问题! //new Vector(); new CopyOnWriteArrayList<>(); Random r = new Random(); diff --git a/src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java b/src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java index ab8183f..9ad35cd 100644 --- a/src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java +++ b/src/main/java/com/mashibing/juc/c_025/T04_ConcurrentQueue.java @@ -21,6 +21,6 @@ public static void main(String[] args) { System.out.println(strs.peek()); System.out.println(strs.size()); - //˫˶Deque + //双端队列Deque } } diff --git a/src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java b/src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java index f74fbc7..385249b 100644 --- a/src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java +++ b/src/main/java/com/mashibing/juc/c_025/T05_LinkedBlockingQueue.java @@ -15,7 +15,7 @@ public static void main(String[] args) { new Thread(() -> { for (int i = 0; i < 100; i++) { try { - strs.put("a" + i); //ˣͻȴ + strs.put("a" + i); //如果满了,就会等待 TimeUnit.MILLISECONDS.sleep(r.nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); @@ -27,7 +27,7 @@ public static void main(String[] args) { new Thread(() -> { for (;;) { try { - System.out.println(Thread.currentThread().getName() + " take -" + strs.take()); //ˣͻȴ + System.out.println(Thread.currentThread().getName() + " take -" + strs.take()); //如果空了,就会等待 } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java b/src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java index 9c3856a..c52e1dd 100644 --- a/src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java +++ b/src/main/java/com/mashibing/juc/c_025/T06_ArrayBlockingQueue.java @@ -16,7 +16,7 @@ public static void main(String[] args) throws InterruptedException { strs.put("a" + i); } - //strs.put("aaa"); //˾ͻȴ + //strs.put("aaa"); //满了就会等待,程序阻塞 //strs.add("aaa"); //strs.offer("aaa"); strs.offer("aaa", 1, TimeUnit.SECONDS); diff --git a/src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java b/src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java index 4c5b262..e04337e 100644 --- a/src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java +++ b/src/main/java/com/mashibing/juc/c_025/T08_SynchronusQueue.java @@ -3,7 +3,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.SynchronousQueue; -public class T08_SynchronusQueue { //Ϊ0 +public class T08_SynchronusQueue { //容量为0 public static void main(String[] args) throws InterruptedException { BlockingQueue strs = new SynchronousQueue<>(); @@ -15,7 +15,7 @@ public static void main(String[] args) throws InterruptedException { } }).start(); - strs.put("aaa"); //ȴ + strs.put("aaa"); //阻塞等待消费者消费 //strs.put("bbb"); //strs.add("aaa"); System.out.println(strs.size()); diff --git a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T01_00_Question.java b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T01_00_Question.java index 39845b5..4b4f36c 100644 --- a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T01_00_Question.java +++ b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T01_00_Question.java @@ -2,6 +2,6 @@ public class T01_00_Question { public static void main(String[] args) { - //要求用线程顺序打印A1B2C3....Z26 + //瑕佹眰鐢ㄧ嚎绋嬮『搴忔墦鍗癆1B2C3....Z26 } } diff --git a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T02_00_LockSupport.java b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T02_00_LockSupport.java index ded1d9b..f60322a 100644 --- a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T02_00_LockSupport.java +++ b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T02_00_LockSupport.java @@ -3,7 +3,7 @@ import java.util.concurrent.locks.LockSupport; -//Locksupport park 当前线程阻塞(停止) +//Locksupport park 褰撳墠绾跨▼闃诲锛堝仠姝級 //unpark(Thread t) public class T02_00_LockSupport { @@ -19,8 +19,8 @@ public static void main(String[] args) throws Exception { for(char c : aI) { System.out.print(c); - LockSupport.unpark(t2); //叫醒T2 - LockSupport.park(); //T1阻塞 + LockSupport.unpark(t2); //鍙啋T2 + LockSupport.park(); //T1闃诲 } }, "t1"); @@ -28,9 +28,9 @@ public static void main(String[] args) throws Exception { t2 = new Thread(() -> { for(char c : aC) { - LockSupport.park(); //t2阻塞 + LockSupport.park(); //t2闃诲 System.out.print(c); - LockSupport.unpark(t1); //叫醒t1 + LockSupport.unpark(t1); //鍙啋t1 } }, "t2"); diff --git a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T03_00_cas.java b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T03_00_cas.java index c71bce9..9425e8b 100644 --- a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T03_00_cas.java +++ b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T03_00_cas.java @@ -5,7 +5,7 @@ public class T03_00_cas { enum ReadyToRun {T1, T2} - static volatile ReadyToRun r = ReadyToRun.T1; //思考为什么必须volatile + static volatile ReadyToRun r = ReadyToRun.T1; //鎬濊�冧负浠�涔堝繀椤籿olatile public static void main(String[] args) { diff --git a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T06_00_sync_wait_notify.java b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T06_00_sync_wait_notify.java index 6317f3f..ffb097e 100644 --- a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T06_00_sync_wait_notify.java +++ b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T06_00_sync_wait_notify.java @@ -14,13 +14,13 @@ public static void main(String[] args) { System.out.print(c); try { o.notify(); - o.wait(); //让出锁 + o.wait(); //璁╁嚭閿� } catch (InterruptedException e) { e.printStackTrace(); } } - o.notify(); //必须,否则无法停止程序 + o.notify(); //蹇呴』锛屽惁鍒欐棤娉曞仠姝㈢▼搴� } }, "t1").start(); @@ -43,4 +43,4 @@ public static void main(String[] args) { } } -//如果我想保证t2在t1之前打印,也就是说保证首先输出的是A而不是1,这个时候该如何做? +//濡傛灉鎴戞兂淇濊瘉t2鍦╰1涔嬪墠鎵撳嵃锛屼篃灏辨槸璇翠繚璇侀鍏堣緭鍑虹殑鏄疉鑰屼笉鏄�1锛岃繖涓椂鍊欒濡備綍鍋氾紵 diff --git a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T09_00_lock_condition.java b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T09_00_lock_condition.java index b31f0e3..3869d20 100644 --- a/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T09_00_lock_condition.java +++ b/src/main/java/com/mashibing/juc/c_026_00_interview/A1B2C3/T09_00_lock_condition.java @@ -1,5 +1,5 @@ /* -Condition本质是锁资源上不同的等待队列 +Condition鏈川鏄攣璧勬簮涓婁笉鍚岀殑绛夊緟闃熷垪 */ package com.mashibing.juc.c_026_00_interview.A1B2C3; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T01_MyExecutor.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T01_MyExecutor.java index 7b184a5..ea01af1 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T01_MyExecutor.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T01_MyExecutor.java @@ -1,5 +1,5 @@ /** - * 认识Executor + * 璁よ瘑Executor */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java index 4b467be..453198d 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T02_ExecutorService.java @@ -1,6 +1,6 @@ /** - * ʶExecutorService,ĶAPIĵ - * ʶsubmitչexecuteһֵ + * 认识ExecutorService,阅读API文档 + * 认识submit方法,扩展了execute方法,具有一个返回值 */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java index f1ccd4a..3baf05e 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T03_Callable.java @@ -1,6 +1,6 @@ /** - * ʶCallableRunnableչ - * Callableĵãзֵ + * 认识Callable,对Runnable进行了扩展 + * 对Callable的调用,可以有返回值 */ package com.mashibing.juc.c_026_01_ThreadPool; @@ -16,9 +16,9 @@ public String call() throws Exception { }; ExecutorService service = Executors.newCachedThreadPool(); - Future future = service.submit(c); //첽 + Future future = service.submit(c); //异步 - System.out.println(future.get());// + System.out.println(future.get());//阻塞 service.shutdown(); } diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java index 259a856..7491c61 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T04_Executors.java @@ -1,5 +1,5 @@ /** - * ʶExecutors + * 认识Executors */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java index 77e3b55..527543a 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T05_ThreadPool.java @@ -1,5 +1,5 @@ /** - * ̳߳صĸ + * 线程池的概念 */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java index f438665..9621291 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_00_Future.java @@ -1,6 +1,6 @@ /** - * ʶfuture - * 첽 + * 认识future + * 异步 */ package com.mashibing.juc.c_026_01_ThreadPool; @@ -16,7 +16,7 @@ public static void main(String[] args) throws InterruptedException, ExecutionExc new Thread(task).start(); - System.out.println(task.get()); // + System.out.println(task.get()); //阻塞 } diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_01_CompletableFuture.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_01_CompletableFuture.java index 74d705f..394a14e 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_01_CompletableFuture.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T06_01_CompletableFuture.java @@ -1,7 +1,7 @@ /** - * 假设你能够提供一个服务 - * 这个服务查询各大电商网站同一类产品的价格并汇总展示 - * @author 马士兵 http://mashibing.com + * 鍋囪浣犺兘澶熸彁渚涗竴涓湇鍔� + * 杩欎釜鏈嶅姟鏌ヨ鍚勫ぇ鐢靛晢缃戠珯鍚屼竴绫讳骇鍝佺殑浠锋牸骞舵眹鎬诲睍绀� + * @author 椹+鍏� http://mashibing.com */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T09_FixedThreadPool.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T09_FixedThreadPool.java index 77664c1..e23db29 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T09_FixedThreadPool.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T09_FixedThreadPool.java @@ -1,5 +1,5 @@ /** - * 线程池的概念 + * 绾跨▼姹犵殑姒傚康 * nasa */ package com.mashibing.juc.c_026_01_ThreadPool; diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T11_WorkStealingPool.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T11_WorkStealingPool.java index bb3c030..f6f5864 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T11_WorkStealingPool.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T11_WorkStealingPool.java @@ -19,7 +19,7 @@ public static void main(String[] args) throws IOException { service.execute(new R(2000)); //daemon service.execute(new R(2000)); - //由于产生的是精灵线程(守护线程、后台线程),主线程不阻塞的话,看不到输出 + //鐢变簬浜х敓鐨勬槸绮剧伒绾跨▼锛堝畧鎶ょ嚎绋嬨�佸悗鍙扮嚎绋嬶級锛屼富绾跨▼涓嶉樆濉炵殑璇濓紝鐪嬩笉鍒拌緭鍑� System.in.read(); } diff --git a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T13_ParallelStreamAPI.java b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T13_ParallelStreamAPI.java index 502cf26..a121dc9 100644 --- a/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T13_ParallelStreamAPI.java +++ b/src/main/java/com/mashibing/juc/c_026_01_ThreadPool/T13_ParallelStreamAPI.java @@ -17,7 +17,7 @@ public static void main(String[] args) { long end = System.currentTimeMillis(); System.out.println(end - start); - //ʹparallel stream api + //使用parallel stream api start = System.currentTimeMillis(); nums.parallelStream().forEach(T13_ParallelStreamAPI::isPrime); diff --git a/src/main/java/com/mashibing/juc/c_027_future_to_loom/T01_Future.java b/src/main/java/com/mashibing/juc/c_027_future_to_loom/T01_Future.java index 6efcd6b..783cf20 100644 --- a/src/main/java/com/mashibing/juc/c_027_future_to_loom/T01_Future.java +++ b/src/main/java/com/mashibing/juc/c_027_future_to_loom/T01_Future.java @@ -1,8 +1,8 @@ /** - * 使用future进行异步编程 - * 缺点: - * 不知道何时结束 - * 阻塞获取结果 + * 浣跨敤future杩涜寮傛缂栫▼ + * 缂虹偣锛� + * 涓嶇煡閬撲綍鏃剁粨鏉� + * 闃诲鑾峰彇缁撴灉 */ package com.mashibing.juc.c_027_future_to_loom; diff --git a/src/main/java/com/mashibing/juc/c_027_future_to_loom/T02_ListenableFuture.java b/src/main/java/com/mashibing/juc/c_027_future_to_loom/T02_ListenableFuture.java index d0fd913..656c559 100644 --- a/src/main/java/com/mashibing/juc/c_027_future_to_loom/T02_ListenableFuture.java +++ b/src/main/java/com/mashibing/juc/c_027_future_to_loom/T02_ListenableFuture.java @@ -1,5 +1,5 @@ /** - * 代码不好维护 + * 浠g爜涓嶅ソ缁存姢 */ package com.mashibing.juc.c_027_future_to_loom; From 8c797b1d316e67ff1fe38bcd997e82e7a4f91b3e Mon Sep 17 00:00:00 2001 From: northleafup Date: Thu, 26 Mar 2020 12:28:05 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B3=A8=E9=87=8Avarhandler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../T01_HelloVarHandle.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/mashibing/juc/c_021_03_VarHandle/T01_HelloVarHandle.java b/src/main/java/com/mashibing/juc/c_021_03_VarHandle/T01_HelloVarHandle.java index 65afb67..3f47e82 100644 --- a/src/main/java/com/mashibing/juc/c_021_03_VarHandle/T01_HelloVarHandle.java +++ b/src/main/java/com/mashibing/juc/c_021_03_VarHandle/T01_HelloVarHandle.java @@ -1,37 +1,37 @@ package com.mashibing.juc.c_021_03_VarHandle; import java.lang.invoke.MethodHandles; -import java.lang.invoke.VarHandle; +//import java.lang.invoke.VarHandle; public class T01_HelloVarHandle { int x = 8; - - private static VarHandle handle; - - static { - try { - handle = MethodHandles.lookup().findVarHandle(T01_HelloVarHandle.class, "x", int.class); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - public static void main(String[] args) { - T01_HelloVarHandle t = new T01_HelloVarHandle(); - - //plain read / write - System.out.println((int)handle.get(t)); - handle.set(t,9); - System.out.println(t.x); - - handle.compareAndSet(t, 9, 10); - System.out.println(t.x); - - handle.getAndAdd(t, 10); - System.out.println(t.x); - - } +// +// private static VarHandle handle; +// +// static { +// try { +// handle = MethodHandles.lookup().findVarHandle(T01_HelloVarHandle.class, "x", int.class); +// } catch (NoSuchFieldException e) { +// e.printStackTrace(); +// } catch (IllegalAccessException e) { +// e.printStackTrace(); +// } +// } +// +// public static void main(String[] args) { +// T01_HelloVarHandle t = new T01_HelloVarHandle(); +// +// //plain read / write +// System.out.println((int)handle.get(t)); +// handle.set(t,9); +// System.out.println(t.x); +// +// handle.compareAndSet(t, 9, 10); +// System.out.println(t.x); +// +// handle.getAndAdd(t, 10); +// System.out.println(t.x); +// +// } }