多线程高并发笔记

1.进程,线程

    进程:程序的一次执行 QQ,动态概念

    线程:进程里最小的执行单元叫线程,一个程序里线程不同的执行路径

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:07
 */
public class T01_WhatsThread {

   
private static class T1 extends Thread {
       
@Override
       
public void run() {
           
for (int i = 0; i < 10; i++) {
               
try {
                   
TimeUnit.MICROSECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println("T1");
            }
        }
    }

   
public static void main(String[] args) {
       
new T1().start();//调度新的线程进程执行
       
//new T1().run(); 为执行类的方法
       
for (int i = 0; i < 10; i++) {
           
try {
               
TimeUnit.MICROSECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
            
System.out.println("main");
        }
    }
}

2.创建线程的方式

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:29
 */
public class T02_HowToCreateThread {
   
static class MyThread extends Thread {
       
@Override
       
public void run() {
           
System.out.println("MyThreadrun方法执行了");
        }
    }

   
static class MyRunnable implements Runnable {

       
@Override
       
public void run() {
           
System.out.println("MyRunnablerun方法执行了");
        }
    }

   
public static void main(String[] args) {
       
new MyThread().start();
       
new Thread(new MyRunnable()).start();

       
new Thread(() -> {
           
System.out.println("lambda多线程的run方法执行了");
        })
.start();
    }
}

//启动线程的方式:1.继承Thread 2.实现Runnable 3.线程池起线程Executors.newCachedThread(内部用的前两种)

 

3.线程基本方法

3.1sleep, Thread.sleep(500);

当前线程暂停一段时间让给其他线程去执行,睡眠完回到就绪队列

3.2yield, Thread.yield();

非常谦让的退出一下,进入等待队列

3.3join t1.join();

把其他线程加入此线程,等加入的执行完在执行当前线程

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:55
 */
public class T03_Sleep_Yield_Join {
   
public static void main(String[] args) {
//        testSleep();
//        testYield();
       
testJoin();
    }

   
static void testSleep() {
       
new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
               
System.out.println("A" + i);
               
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        }).
start();
    }

   
static void testYield() {
       
new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
                
System.out.println("y" + i);
               
if (i % 10 == 0) {
                   
Thread.yield();
                }
            }
        }).
start();
    }

   
static void testJoin() {
       
Thread t1 = new Thread(() -> {
           
for (int i = 0; i < 100; i++) {
               
System.out.println("t1A" + i);
               
try {
                    
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        },
"t1");
       
Thread t2 = new Thread(() -> {

           
try {
               
t1.join();

            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
for (int i = 0; i < 100; i++) {
               
System.out.println("t2B" + i);
               
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        },
"t2");
       
t1.start();
       
t2.start();
    }
}

4.线程的状态

绿色块6个状态

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:00
 */
public class T03_ThreadState {
   
static class MyThread extends Thread {
       
@Override
       
public void run() {
           
System.out.println(this.getState());
           
for (int i = 0; i < 10; i++) {
                
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println(i);
            }
        }
    }

   
public static void main(String[] args) {
       
Thread t = new MyThread();
       
System.out.println(t.getState());
       
t.start();

       
try {
           
//确保线程执行完再执行后面的代码
           
t.join();
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(t.getState());
    }
}

 

5.synchronized

5.1基本用法

锁定对象不能为String常量 Integer Long等基本数据类型,String所有引用用的一个,会出现异常,

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:17
 */
public class T04_Synchronized {
   
private int count = 10;
   
private Object o = new Object();

   
public void m() {
       
synchronized (o) {
           
count--;
           
System.out.println(Thread.currentThread().getName() + " count=" + count);
        }
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:24
 */
public class T05_SynchronizedThis {
   
private int count = 10;

   
public void m() {
       
//等价与synchronized方法
       
synchronized (this) {
           
count--;
           
System.out.println(Thread.currentThread().getName() + "count =" + count);
        }
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:27
 */
public class T06_SynchronizedMathod {
   
private int count = 10;

   
public synchronized void m() {
       
count--;
       
System.out.println(Thread.currentThread().getName() + "count =" + count);
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:30
 */
public class T07_SynchronizedClass {
   
private static int count = 10;

   
//等同于synchronized(T07_SynchronizedClass.class);
   
public synchronized static void m() {
       
count--;
       
System.out.println(Thread.currentThread().getName() + "count=" + count);
    }

   
public static void mm() {
       
synchronized (T07_SynchronizedClass.class) {
           
count--;
        }
    }
}

5.2synchronized方法可以跟synchronized方法同时执行,至少两个线程进行验证

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 10:44
 */
public class T09_SynchronizedAndNotSyn {

   
public synchronized void m1() {
       
System.out.println(Thread.currentThread().getName() + "m1 start...");
       
try {
           
Thread.sleep(10000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(Thread.currentThread().getName() + "m1 end");
    }

   
public void m2() {
       
try {
           
Thread.sleep(5000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(Thread.currentThread().getName() + "m2");
    }

   
public static void main(String[] args) {
       
T09_SynchronizedAndNotSyn t = new T09_SynchronizedAndNotSyn();
       
//验证非synchronized方法会跟非syn方法同时执行,两个线程进行执行,输出结果可以看到
       
new Thread(t::m1, "t1").start();
       
new Thread(t::m2, "t2").start();
    }
}

案列,读到中间结果

/**
 *
面试题:模拟银行账户
 
* 对业务写方法加锁
 
* 对业务读方法不加锁
 
* 这样行不行?
 
*
 *
容易产生脏读问题(dirtyRead
 
*/
package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:04
 */
public class Account {
   
String name;
   
double balance;

   
public synchronized void set(String name, double balance) {
        
this.name = name;
       
try {
           
Thread.sleep(2000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
this.balance = balance;
    }

   
public double get(String name) {
       
return this.balance;
    }

   
public static void main(String[] args) {
       
Account a = new Account();
       
new Thread(() -> {
            
a.set("张三", 100);
        },
"set线程").start();

       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }

       
System.out.println(a.get("张三"));
       
try {
            
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(a.get("张三"));
    }


}

5.3可重入性

       Synchronized是可重入锁,也就是两个方法都进行了synchronized加锁,一个掉另一个,同一个线程内感知倒已经获取到锁,则可以进行调用,否则会导致死锁

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:29
 */
public class T10_CanRepeatSynchronized {

   
public synchronized void m1(){
       
System.out.println("m1 start");
        
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
m2();
       
System.out.println("m1 end");
    }

   
public synchronized  void m2(){
       
try {
           
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("m2");
    }

   
public static void main(String[] args) {
       
T10_CanRepeatSynchronized t=new T10_CanRepeatSynchronized();
       
new Thread(t::m1).start();
    }
}

输出结果

m1 start

m2

m1 end

子类的synchronized可以调用父类的,否则会出现死锁

        package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:39
 */
public class T11_CanRepeatSynchronized02 {
   
public synchronized void m() {
       
System.out.println("m start");
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("m end");
    }

   
public static void main(String[] args) {
       
new T11_Child().m();

    }
}

class T11_Child extends T11_CanRepeatSynchronized02 {
   
@Override
   
public synchronized void m() {
       
System.out.println("child m start");
       
super.m();
       
System.out.println("child m end");
    }
}

输出结果

child m start

m start

m end

child m end

5.4异常会导致锁释放,可能会导致程序乱入

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:53
 */
public class T12_ExceptionOutSynch {
   
int count = 0;

   
public synchronized void m() {
       
System.out.println(Thread.currentThread().getName() + "start");
       
while (true) {
           
count++;
           
System.out.println(Thread.currentThread().getName() + "count=" + count);
           
try {
               
TimeUnit.SECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
if (count == 5) {
               
int i = 1 / 0;
               
System.out.println("出现异常了");
            }
        }
    }

   
public static void main(String[] args) {
       
T12_ExceptionOutSynch t = new T12_ExceptionOutSynch();
       
Runnable runnable = new Runnable() {
           
@Override
           
public void run() {
               
t.m();
            }
        };
       
new Thread(runnable).start();
       
try {
           
TimeUnit.SECONDS.sleep(3);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
new Thread(t::m).start();
    }

}

发生异常原本没有机会执行的线程得到执行机会,会乱入执行

5.4底层实现原理

JDK1.5之前是重量级的-OS

之后开始优化

1)刚开始是无锁状态

2)当有线程进行访问,在对象头的两位进行记录,markword记录线程ID,也就是偏向锁,此线程可以直接进行下一次调用

3)当有线程进行争用的时候,升级为自旋锁,争用线程不会立即进入就绪队列,而是会while 等待10次,10次之后进入下一阶段(占用cpu,不访问操作系统,用户态非内核态)

4)升级为重量级锁-OS,线程进入等待序列,不在占用cpu

执行时间长选系统锁,执行时间短,线程不是很多的情况下选择自旋锁。

6.volatile

作用:保证线程可见性;禁止指令重排序

6.1保证线程可见性

       -MESI

       -缓存一致性协议,多个cpu之间

(不同线程会对堆内存的变量复制到本地进行操作,操作完然后写入,所以即使操作完写入其他线程也无法感知到)

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/9 0:24
 */
public class T13_Volatile {
   
//不加volatile,当另一个线程修改字段值,主线程无法感知到
   
/*volatile*/ boolean running=true;
   
void m(){
       
System.out.println("m start");
       
while(running){

        }
       
System.out.println("m end");
    }

    
public static void main(String[] args) {
       
T13_Volatile t=new T13_Volatile();
       
new Thread(t::m).start();
       
try {
           
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
t.running=false;
    }
}

 

 

6.2禁止指令重排序

Cpu执行指令会进行同时执行,存在顺序调换的可能

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/9 1:02
 */
public class T14_VolatileSingle {
   
private T14_VolatileSingle() {
    }

   
private static volatile T14_VolatileSingle INSTANCE;

   
public static T14_VolatileSingle getInstance() {

       
if (INSTANCE == null) {
           
//DCL双重检查
           
synchronized (T14_VolatileSingle.class) {
               
if (INSTANCE == null) {
                   
try {
                       
Thread.sleep(1);
                    }
catch (InterruptedException e) {
                       
e.printStackTrace();
                    }
                   
INSTANCE = new T14_VolatileSingle();
                }
            }
        }
       
return INSTANCE;
    }

   
public static void main(String[] args) {
       
for (int i = 0; i < 100000; i++) {
           
new Thread(() -> {
               
System.out.println(T14_VolatileSingle.getInstance().hashCode());
            })
.start();
        }
    }
}

添加volatile的原因,INSTANCE = new T14_VolatileSingle();创建对象的过程分为三步
第一步:给对象申请内存,并赋为初始值

第二步:给对象将值赋为真正的值

第三步:将变量指向对象

 

第三步跟第二步发生指令重排序,此时变量指向的对象已经不是null,但是也不是真正的值,获取此数据直接去使用会有异常,是不正确的。

Volatile会禁止指令重排序,以下程序有volatile没有synchronized也是不正确的,修改后其他线程可见,但是++内部会分很多步执行,其他线程会对相同值进行++后赋值,会比实际的小

Volatile不能替代synchronized,只是保证可见性package com.hy.mashibing2.knowledge;

import java.util.ArrayList;

/**
 *
@author hanyong
 *
@date 2020/9/9 22:33
 */
public class T15_VolatileCanNotReplaceSyn {
  
volatile int  count = 0;

  
synchronized void  m() {
       
for (int i = 0; i < 10000; i++) {
           
count++;
        }
    }

   
public static void main(String[] args) {
       
T15_VolatileCanNotReplaceSyn t = new T15_VolatileCanNotReplaceSyn();
       
ArrayList<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

7.锁其他点

 

7.1细化锁,粗化锁

细化尽可能的锁最少的代码,粗化锁当方法征用频繁的时候粗胡下

package com.hy.mashibing2.knowledge;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 *
细化锁
 
*
 *
@author hanyong
 *
@date 2020/9/9 22:53
 */
public class T16_FineLock {
   
volatile int count = 0;

   
void m() {
       
try {
           
//业务逻辑
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
synchronized (this) {
            
count++;
        }
       
try {
           
//业务逻辑
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
            
e.printStackTrace();
        }
    }

   
public static void main(String[] args) {
       
T16_FineLock t = new T16_FineLock();
       
ArrayList<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

7.2锁同一对象

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/9 23:04
 */
public class T17_SynSameObject {
   
final Object o = new Object();//final防止被重新赋值

   
void m() {
       
synchronized (o) {
           
while (true) {
               
try {
                   
TimeUnit.SECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println(Thread.currentThread().getName());
            }
        }
    }

   
public static void main(String[] args) {
       
T17_SynSameObject t = new T17_SynSameObject();
       
new Thread(t::m, "thread1").start();
       
new Thread(t::m, "thread2").start();
//        t.o = new Object();//注释掉后thread2不会执行,此处对象变成另一个对象,先执行的线程锁不住第二个线程
   
}
}

8.CAS

8.1AtomicInteger使用案列

 

package com.hy.mashibing2.knowledge;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
@author hanyong
 *
@date 2020/9/9 23:30
 */
public class T18_AtomicInteger {
   
AtomicInteger count=new AtomicInteger(0);

   
void m() {
       
for (int i = 0; i < 1000; i++) {
           
count.incrementAndGet();
        }
    }

   
public static void main(String[] args) {
        
T18_AtomicInteger t = new T18_AtomicInteger();
       
List<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

8.2原理

内部调用UnsafegetAndAddInt方法

public final int getAndAddInt(Object var1, long var2, int var4) {
   
int var5;
   
do {
       
var5 = this.getIntVolatile(var1, var2);
    }
while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

   
return var5;
}

cas(v,excepted,NewValue); v为之前获得值,e为期待值,n为要设定的新值

if(v==e)

v=new

否则重试。Cascpu原语级别,执行过程不会被打断,也就是不怕其他线程打断出错

ABA问题,解决思路加version

8.3atomic synchronized Longadder性能大比拼

package com.hy.mashibing2.knowledge;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;

/**
 *
@author hanyong
 *
@date 2020/9/10 23:31
 */
public class T19_AtomicvsSynvsLongAdder {

   
static AtomicInteger count1 = new AtomicInteger(0);
   
static long count2 = 0L;
   
static LongAdder count3 = new LongAdder();


   
public static void main(String[] args) {

       
Thread[] threads = new Thread[1000];
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
for (int k = 0; k < 10000; k++) {
                   
count1.incrementAndGet();
                }

            })
;

        }
       
long atomiStartTime = System.currentTimeMillis();
       
for (Thread thread : threads) {
           
thread.start();
        }
       
for (Thread thread : threads) {
           
try {
                
thread.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long atomEndTime = System.currentTimeMillis();
       
System.out.println("AtomicInteger" + count1.get() + "耗时:" + (atomEndTime - atomiStartTime));

       
final Object o = new Object();
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(new Runnable() {
               
@Override
               
public void run() {
                    
for (int k = 0; k < 10000; k++) {
                       
synchronized (o) {
                           
count2++;
                        }
                    }
                }
            })
;
        }
       
long longStartTime = System.currentTimeMillis();
       
for (Thread t : threads) {
           
t.start();
        }
       
for (Thread t : threads) {
           
try {
               
t.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long longEndTime = System.currentTimeMillis();
       
System.out.println("synch" + count2 + "耗时:" + (longEndTime - longStartTime));


       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
for (int k = 0; k < 10000; k++) {
                   
count3.increment();
                }
            })
;
        }

       
long longAddStartTime = System.currentTimeMillis();
       
for (Thread t : threads) {
           
t.start();
        }
       
for (Thread t : threads) {
           
try {
               
t.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long longAddEndTime = System.currentTimeMillis();
        
System.out.println("LongAdd" + count3.longValue() + "耗时:" + (longAddEndTime - longAddStartTime));
    }

}

输出结果:

AtomicInteger10000000耗时:203

synch10000000耗时:549

LongAdd10000000耗时:135

矩形: 圆角: SumLongAdder线程多时效率最高,原因LongAdder内部会有一个数组,将数字放到数组中,不同部分线程对数组的某个索引值进行递增,最终对数组所有元素进行递增,内部实现也是CAS所以较快。

                   
    文本框: 0
  文本框: 0   文本框: 0   文本框: 0
         
 
 

 

 


250个线程对第一个进行递增,250线程对第二个进行递增,。。。最终进行相加得到结果

9.新型锁

9.1reentrantLock可重入性

可重入性,不同线程存在竞争,但是相同线程执行一个方法,当方法内部调用其他加锁方法时,当synch锁的是同一个对象就可以进行调用。可重入性

package com.hy.mashibing2.knowledge;
import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/11 0:31
 */
public class T20_ReentrantLock1 {
   
synchronized void m1() {
       
for (int i = 0; i < 10; i++) {
           
try {
               
TimeUnit.SECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(i);
           
if(i==2){
               
m2();
            }
        }
    }

   
synchronized void m2() {
       
System.out.println("m2执行了");
    }

   
public static void main(String[] args) {
       
T20_ReentrantLock1 t = new T20_ReentrantLock1();
       
new Thread(t::m1).start();
//        new Thread(t::m2).start();
   
}
}

9.2reentrantLock基本用法

作用同synchronizedTryfinally使用。使用前lock,finally里面unlock

package com.hy.mashibing2.knowledge;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 18:57
 */
public class T21_ReentrantLock2 {

   
ReentrantLock lock = new ReentrantLock();

   
void m1() {
       
try {
            
lock.lock();
           
for (int i = 0; i < 10; i++) {
               
TimeUnit.SECONDS.sleep(1);
               
System.out.println("m" + i);
            }
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
finally {
           
lock.unlock();
        }

    }

   
void m2() {
       
try {
           
lock.lock();
           
System.out.println("m2执行了");
        }
finally {
           
lock.unlock();
        }


    }

   
public static void main(String[] args) {
       
T21_ReentrantLock2 t = new T21_ReentrantLock2();
       
new Thread(t::m1).start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
new Thread(t::m2).start();

    }
}

9.3reentrantLock lock.tryLock案例

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 21:24
 */
public class T23_ReentrantLock3 {
   
ReentrantLock lock = new ReentrantLock();

   
void m1() {
       
try {
           
lock.lock();
           
for (int i = 0; i < 3; i++) {
               
TimeUnit.SECONDS.sleep(1);
               
System.out.println(i);
            }
        }
catch (Exception e) {
           
e.printStackTrace();
        }
finally {
           
lock.unlock();
        }
    }

   
/**
     *
使用tryLock进行尝试锁定,无论锁定与否,方法都会继续执行
    
* 可以根据tryLock的返回值来判断是否锁定
    
* 也可指定tryLock的时间
    
*/
   
void m2() {
       
boolean locked = false;
       
try {
           
//5秒钟之内一直去获得锁,如果获得锁,locked就为true,
           
locked = lock.tryLock(3, TimeUnit.SECONDS);
            
System.out.println("m2方法执行了"+locked);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
finally {
           
if (locked) {
               
lock.unlock();
            }
        }
    }

   
public static void main(String[] args) {
       
T23_ReentrantLock3 t=new T23_ReentrantLock3();
       
new Thread(t::m1).start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
        
new Thread(t::m2).start();
    }
}

9.4 reentrantLock lock.lockInterruptibly可被打断,执行catch块的方法

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 23:41
 */
public class T24_ReentrantLock4 {

   
public static void main(String[] args) {
       
ReentrantLock lock = new ReentrantLock();
       
Thread t1=new Thread(()->{
           
try {
               
lock.lock();
               
System.out.println("线程1start");
               
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
               
System.out.println("线程1end");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
lock.unlock();
            }
        },
"线程1");
       
Thread t2=new Thread(()->{
           
try{
               
lock.lockInterruptibly();
               
System.out.println("线程2执行开始");
               
TimeUnit.SECONDS.sleep(5);
               
System.out.println("线程2执行结束");
            }
catch (InterruptedException e) {
               
System.out.println("m2被打断"+e.getMessage());
               
e.printStackTrace();
            }
finally {
               
lock.unlock();
            }
        },
"线程2");
       
t1.start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
t2.start();

       
t2.interrupt();
    }
}

 

9.5reentrantLock公平锁

一个线程执行完,另一个线程再执行,新加过来的线程进入等待队列,有序队列,排队执行。不会乱序争抢

package com.hy.mashibing2.knowledge;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/13 0:09
 */
public class T25_ReentrantLock5 extends Thread {

   
//公平锁
   
private static ReentrantLock lock = new ReentrantLock(true);

   
@Override
   
public void run() {
       
for (int i = 0; i < 100; i++) {
           
try {
               
lock.lock();
               
System.out.println(Thread.currentThread().getName() + "获得锁");
            }
finally {
                
lock.unlock();
            }
        }
    }

   
public static void main(String[] args) {
       
T25_ReentrantLock5 t = new T25_ReentrantLock5();
       
Thread thread1 = new Thread(t, "线程1");
       
Thread thread2 = new Thread(t, "线程2");
        
thread1.start();
       
thread2.start();
    }
}

打印结果

线程2获得锁

线程1获得锁

线程2获得锁

线程1获得锁

9.6CountDownLatch

package com.hy.mashibing2.knowledge;

import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch
倒数门闩
 
*
 *
@author hanyong
 *
@date 2020/9/14 21:45
 */
public class T26_CountDownLatch1 {

   
public static void main(String[] args) {

    }

   
private static void usingCountDownLatch() {
       
Thread[] threads = new Thread[100];
       
CountDownLatch latch = new CountDownLatch(threads.length);
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
int result = 0;
               
for (int j = 0; j < 10000; j++) {
                   
result += j;
                   
latch.countDown();
                }
            })
;
        }

       
for (int i = 0; i < threads.length; i++) {
           
threads[i].start();
        }

       
try {
           
latch.await(); //所有的线程latch.countDown();执行完,门闩打开执行后面的代码
       
} catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("end latch");
    }

   
private static void usingJoin() {
       
Thread[] threads = new Thread[100];
       
for (int i = 0; i < threads.length; i++) {
            
threads[i] = new Thread(() -> {
               
int result = 0;
               
for (int j = 0; j < 10000; j++) {
                   
result += j;
                }
            })
;
        }

       
for (int i = 0; i < threads.length; i++) {
            
threads[i].start();
        }

       
for (int i = 0; i < threads.length; i++) {
           
try {
               
threads[i].join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
    }

}

9.7CyclicBarrier 栅栏,满后执行

package com.hy.mashibing2.knowledge;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 *
 * CyclicBarrier
栅栏,满了之后做后续动作
 
* @author hanyong
 *
@date 2020/9/14 23:29
 */
public class T27_CyclicBarrier {


    
public static void main(String[] args) {

//        CyclicBarrier barrier = new CyclicBarrier(20);
       
CyclicBarrier barrier = new CyclicBarrier(20,()->{
           
System.out.println("lamda满人发车");
        });
       
/* CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
            @Override
            public void run() {
                System.out.println("
人满发车");
            }
        });*/

       
Thread[] threads = new Thread[100];
       
for (int i = 0; i < threads.length; i++) {
            
new Thread(() -> {
               
try {
                   
barrier.await();
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
catch (BrokenBarrierException e) {
                   
e.printStackTrace();
                }
            })
.start();
        }
    }
}

 

9.8Phaser阶段锁

所有线程执行完当前阶段再开始执行下一阶段

phaser.arriveAndAwaitAdvance();

phaser.arriveAndDeregister();

package com.hy.mashibing2.knowledge;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/15 0:19
 */
public class T28_Phaser1 {

   
static Random r = new Random();
   
static Phaser phaser = new MarriagePhaser();

   
static void sleep(int nums) {
       
try {
            
TimeUnit.MILLISECONDS.sleep(nums);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
    }

   
public static void main(String[] args) {
       
phaser.bulkRegister(7);
       
for (int i = 0; i < 5; i++) {
            
new Thread(new Persion("p" + i)).start();
        }
       
new Thread(new Persion("新郎")).start();
       
new Thread(new Persion("新娘")).start();
    }

   
static class MarriagePhaser extends Phaser {
       
@Override
       
protected boolean onAdvance(int phase, int registeredParties) {
           
switch (phase) {
               
case 0:
                   
System.out.println("所有人到齐了!" + registeredParties);
                   
System.out.println();
                   
return false;
                
case 1:
                   
System.out.println("所有人吃完了!" + registeredParties);
                   
System.out.println();
                   
return false;
               
case 2:
                   
System.out.println("所有人离开了!" + registeredParties);
                   
System.out.println();
                   
return false;
               
case 3:
                   
System.out.println("婚礼结束!新娘新郎抱抱" + registeredParties);
                   
return true;
               
default:
                    
return true;
            }

        }
    }

   
static class Persion implements Runnable {
       
String name;

       
public Persion(String name) {
           
this.name = name;
        }

      
void arrive() {
           
sleep(1000);
           
System.out.printf("%s 到达现场! \n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void eat() {
           
sleep(1000);
           
System.out.printf("%s 吃完!\n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void leave() {
           
sleep(1000);
           
System.out.printf("%s 离开!\n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void hug() {
           
if (name.equals("新郎") || name.equals("新娘")) {
               
sleep(1000);
               
System.out.printf("%s 洞房!\n", name);
               
phaser.arriveAndAwaitAdvance();
            }
else {
               
phaser.arriveAndDeregister();
            }

        }

       
@Override
       
public void run() {

            
arrive();
           
eat();
           
leave();
           
hug();
        }
    }
}

9.9读写锁

static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();
static Lock writeLock = readWriteLock.writeLock();

readLock为共享锁,读线程可以同时执行,writeLock为排他锁,独占执行

案例如下

package com.hy.mashibing2.knowledge;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
@author hanyong
 *
@date 2020/9/15 23:20
 */
public class T29_ReadWriterLock {

   
static int value;
   
static ReentrantLock lock = new ReentrantLock();
   
static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
   
static Lock readLock = readWriteLock.readLock();
   
static Lock writerLock = readWriteLock.writeLock();

   
public static void read(Lock lock) {
       
try {
           
lock.lock();

           
sleep(1);
            
System.out.println(Thread.currentThread().getName() + "读完了");
        }
finally {
           
lock.unlock();

        }
    }

   
public static void writer(Lock lock, int v) {
       
try {
           
lock.lock();

           
sleep(1);
           
value = v;
           
System.out.println(Thread.currentThread().getName() + "写完了");
        }
finally {
           
lock.unlock();

        }
    }

   
public static void main(String[] args) {
       
//创建10个线程读
       
for (int i = 0; i < 10; i++) {
            
new Thread(() -> {
               
read(readLock);
            },
"读线程" + i).start();
        }

       
//创建2个线程写
       
for (int i = 0; i < 2; i++) {
           
new Thread(() -> {
               
writer(writerLock, new Random().nextInt());
            },
"写线程" + i).start();
        }
    }

   
static void sleep(int time) {
       
try {
           
TimeUnit.SECONDS.sleep(time);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
    }
}

 

9.10semaphore信号量

做限流

package com.hy.mashibing2.knowledge;

import java.util.concurrent.Semaphore;

/**
 *
@author hanyong
*
@date 2020/9/16 22:09
 */
public class T30_Semaphore {
   
public static void main(String[] args) {
       
//1表示同时只能有一个线程执行
       
//Semaphore semaphore=new Semaphore(1);
       
Semaphore semaphore=new Semaphore(1,true);//公平锁,队列,线程排队

       
new Thread(()->{

           
try {
               
semaphore.acquire();//阻塞获得,后为0
               
System.out.println("T1 running...");
               
Thread.sleep(200);
               
System.out.println("T1 running...");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
semaphore.release();//释放,后为1
           
}
        },
"t1").start();

       
new Thread(()->{
           
try {
               
semaphore.acquire();
               
System.out.println("T2 running");
               
Thread.sleep(200);
               
System.out.println("T2 running");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
semaphore.release();
            }
        },
"t2").start();
    }
}

 

9.11Exchanger交换

*/
public class T31_Exchange {

   
static Exchanger<String> exchanger = new Exchanger();

   
public static void main(String[] args) {
       
new Thread(() -> {
           
String s = "t1";
           
try {
              
s= exchanger.exchange(s);//双人游戏交换装备
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(Thread.currentThread().getName() + s);
        },
"线程1").start();
       
new Thread(() -> {
           
String s = "t2";
           
try {
              
s= exchanger.exchange(s);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(Thread.currentThread().getName() + s);
        },
"线程2").start();
    }
}

打印结果

线程1t2

线程2t1

9.12LockSupport

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 *
 * LockSupport.park();
不用加锁可以暂停线程
 
* LockSupport.unpark(t);可以恢复park的线程继续执行
 
* LockSupport.unpark(t);可以优先于LockSupport.park();执行,这样park的时候可以不用park
 *
 *
内部实现类似于维护一个count,park变为0unpark变为1,变为1线程继续执行,之前已经为1park不停继续执行,再次变为0就停
 
* @author hanyong
 *
@date 2020/9/16 23:49
 */
public class T32_LockSupport {

   
public static void main(String[] args) {
       
Thread t = new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
               
System.out.println(i);
               
if (i == 5) {
                   
LockSupport.park();
                }
               
try {
                   
TimeUnit.SECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        })
;
       
t.start();
       
LockSupport.unpark(t);
       
/*try {
            TimeUnit.SECONDS.sleep(8);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("
主线程睡了8秒了");
        LockSupport.unpark(t);*/
   
}
}

 

 

1.进程,线程

    进程:程序的一次执行 QQ,动态概念

    线程:进程里最小的执行单元叫线程,一个程序里线程不同的执行路径

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:07
 */
public class T01_WhatsThread {

   
private static class T1 extends Thread {
       
@Override
       
public void run() {
           
for (int i = 0; i < 10; i++) {
               
try {
                   
TimeUnit.MICROSECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println("T1");
            }
        }
    }

   
public static void main(String[] args) {
       
new T1().start();//调度新的线程进程执行
       
//new T1().run(); 为执行类的方法
       
for (int i = 0; i < 10; i++) {
           
try {
               
TimeUnit.MICROSECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
            
System.out.println("main");
        }
    }
}

2.创建线程的方式

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:29
 */
public class T02_HowToCreateThread {
   
static class MyThread extends Thread {
       
@Override
       
public void run() {
           
System.out.println("MyThreadrun方法执行了");
        }
    }

   
static class MyRunnable implements Runnable {

       
@Override
       
public void run() {
           
System.out.println("MyRunnablerun方法执行了");
        }
    }

   
public static void main(String[] args) {
       
new MyThread().start();
       
new Thread(new MyRunnable()).start();

       
new Thread(() -> {
           
System.out.println("lambda多线程的run方法执行了");
        })
.start();
    }
}

//启动线程的方式:1.继承Thread 2.实现Runnable 3.线程池起线程Executors.newCachedThread(内部用的前两种)

 

3.线程基本方法

3.1sleep, Thread.sleep(500);

当前线程暂停一段时间让给其他线程去执行,睡眠完回到就绪队列

3.2yield, Thread.yield();

非常谦让的退出一下,进入等待队列

3.3join t1.join();

把其他线程加入此线程,等加入的执行完在执行当前线程

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/4 23:55
 */
public class T03_Sleep_Yield_Join {
   
public static void main(String[] args) {
//        testSleep();
//        testYield();
       
testJoin();
    }

   
static void testSleep() {
       
new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
               
System.out.println("A" + i);
               
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        }).
start();
    }

   
static void testYield() {
       
new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
                
System.out.println("y" + i);
               
if (i % 10 == 0) {
                   
Thread.yield();
                }
            }
        }).
start();
    }

   
static void testJoin() {
       
Thread t1 = new Thread(() -> {
           
for (int i = 0; i < 100; i++) {
               
System.out.println("t1A" + i);
               
try {
                    
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        },
"t1");
       
Thread t2 = new Thread(() -> {

           
try {
               
t1.join();

            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
for (int i = 0; i < 100; i++) {
               
System.out.println("t2B" + i);
               
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        },
"t2");
       
t1.start();
       
t2.start();
    }
}

4.线程的状态

绿色块6个状态

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:00
 */
public class T03_ThreadState {
   
static class MyThread extends Thread {
       
@Override
       
public void run() {
           
System.out.println(this.getState());
           
for (int i = 0; i < 10; i++) {
                
try {
                   
Thread.sleep(500);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println(i);
            }
        }
    }

   
public static void main(String[] args) {
       
Thread t = new MyThread();
       
System.out.println(t.getState());
       
t.start();

       
try {
           
//确保线程执行完再执行后面的代码
           
t.join();
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(t.getState());
    }
}

 

5.synchronized

5.1基本用法

锁定对象不能为String常量 Integer Long等基本数据类型,String所有引用用的一个,会出现异常,

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:17
 */
public class T04_Synchronized {
   
private int count = 10;
   
private Object o = new Object();

   
public void m() {
       
synchronized (o) {
           
count--;
           
System.out.println(Thread.currentThread().getName() + " count=" + count);
        }
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:24
 */
public class T05_SynchronizedThis {
   
private int count = 10;

   
public void m() {
       
//等价与synchronized方法
       
synchronized (this) {
           
count--;
           
System.out.println(Thread.currentThread().getName() + "count =" + count);
        }
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:27
 */
public class T06_SynchronizedMathod {
   
private int count = 10;

   
public synchronized void m() {
       
count--;
       
System.out.println(Thread.currentThread().getName() + "count =" + count);
    }
}

 

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 0:30
 */
public class T07_SynchronizedClass {
   
private static int count = 10;

   
//等同于synchronized(T07_SynchronizedClass.class);
   
public synchronized static void m() {
       
count--;
       
System.out.println(Thread.currentThread().getName() + "count=" + count);
    }

   
public static void mm() {
       
synchronized (T07_SynchronizedClass.class) {
           
count--;
        }
    }
}

5.2synchronized方法可以跟synchronized方法同时执行,至少两个线程进行验证

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/6 10:44
 */
public class T09_SynchronizedAndNotSyn {

   
public synchronized void m1() {
       
System.out.println(Thread.currentThread().getName() + "m1 start...");
       
try {
           
Thread.sleep(10000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(Thread.currentThread().getName() + "m1 end");
    }

   
public void m2() {
       
try {
           
Thread.sleep(5000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(Thread.currentThread().getName() + "m2");
    }

   
public static void main(String[] args) {
       
T09_SynchronizedAndNotSyn t = new T09_SynchronizedAndNotSyn();
       
//验证非synchronized方法会跟非syn方法同时执行,两个线程进行执行,输出结果可以看到
       
new Thread(t::m1, "t1").start();
       
new Thread(t::m2, "t2").start();
    }
}

案列,读到中间结果

/**
 *
面试题:模拟银行账户
 
* 对业务写方法加锁
 
* 对业务读方法不加锁
 
* 这样行不行?
 
*
 *
容易产生脏读问题(dirtyRead
 
*/
package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:04
 */
public class Account {
   
String name;
   
double balance;

   
public synchronized void set(String name, double balance) {
        
this.name = name;
       
try {
           
Thread.sleep(2000);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
this.balance = balance;
    }

   
public double get(String name) {
       
return this.balance;
    }

   
public static void main(String[] args) {
       
Account a = new Account();
       
new Thread(() -> {
            
a.set("张三", 100);
        },
"set线程").start();

       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }

       
System.out.println(a.get("张三"));
       
try {
            
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println(a.get("张三"));
    }


}

5.3可重入性

       Synchronized是可重入锁,也就是两个方法都进行了synchronized加锁,一个掉另一个,同一个线程内感知倒已经获取到锁,则可以进行调用,否则会导致死锁

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:29
 */
public class T10_CanRepeatSynchronized {

   
public synchronized void m1(){
       
System.out.println("m1 start");
        
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
m2();
       
System.out.println("m1 end");
    }

   
public synchronized  void m2(){
       
try {
           
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("m2");
    }

   
public static void main(String[] args) {
       
T10_CanRepeatSynchronized t=new T10_CanRepeatSynchronized();
       
new Thread(t::m1).start();
    }
}

输出结果

m1 start

m2

m1 end

子类的synchronized可以调用父类的,否则会出现死锁

        package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:39
 */
public class T11_CanRepeatSynchronized02 {
   
public synchronized void m() {
       
System.out.println("m start");
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("m end");
    }

   
public static void main(String[] args) {
       
new T11_Child().m();

    }
}

class T11_Child extends T11_CanRepeatSynchronized02 {
   
@Override
   
public synchronized void m() {
       
System.out.println("child m start");
       
super.m();
       
System.out.println("child m end");
    }
}

输出结果

child m start

m start

m end

child m end

5.4异常会导致锁释放,可能会导致程序乱入

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/6 11:53
 */
public class T12_ExceptionOutSynch {
   
int count = 0;

   
public synchronized void m() {
       
System.out.println(Thread.currentThread().getName() + "start");
       
while (true) {
           
count++;
           
System.out.println(Thread.currentThread().getName() + "count=" + count);
           
try {
               
TimeUnit.SECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
if (count == 5) {
               
int i = 1 / 0;
               
System.out.println("出现异常了");
            }
        }
    }

   
public static void main(String[] args) {
       
T12_ExceptionOutSynch t = new T12_ExceptionOutSynch();
       
Runnable runnable = new Runnable() {
           
@Override
           
public void run() {
               
t.m();
            }
        };
       
new Thread(runnable).start();
       
try {
           
TimeUnit.SECONDS.sleep(3);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
new Thread(t::m).start();
    }

}

发生异常原本没有机会执行的线程得到执行机会,会乱入执行

5.4底层实现原理

JDK1.5之前是重量级的-OS

之后开始优化

1)刚开始是无锁状态

2)当有线程进行访问,在对象头的两位进行记录,markword记录线程ID,也就是偏向锁,此线程可以直接进行下一次调用

3)当有线程进行争用的时候,升级为自旋锁,争用线程不会立即进入就绪队列,而是会while 等待10次,10次之后进入下一阶段(占用cpu,不访问操作系统,用户态非内核态)

4)升级为重量级锁-OS,线程进入等待序列,不在占用cpu

执行时间长选系统锁,执行时间短,线程不是很多的情况下选择自旋锁。

6.volatile

作用:保证线程可见性;禁止指令重排序

6.1保证线程可见性

       -MESI

       -缓存一致性协议,多个cpu之间

(不同线程会对堆内存的变量复制到本地进行操作,操作完然后写入,所以即使操作完写入其他线程也无法感知到)

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/9 0:24
 */
public class T13_Volatile {
   
//不加volatile,当另一个线程修改字段值,主线程无法感知到
   
/*volatile*/ boolean running=true;
   
void m(){
       
System.out.println("m start");
       
while(running){

        }
       
System.out.println("m end");
    }

    
public static void main(String[] args) {
       
T13_Volatile t=new T13_Volatile();
       
new Thread(t::m).start();
       
try {
           
TimeUnit.SECONDS.sleep(2);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
t.running=false;
    }
}

 

 

6.2禁止指令重排序

Cpu执行指令会进行同时执行,存在顺序调换的可能

package com.hy.mashibing2.knowledge;

/**
 *
@author hanyong
 *
@date 2020/9/9 1:02
 */
public class T14_VolatileSingle {
   
private T14_VolatileSingle() {
    }

   
private static volatile T14_VolatileSingle INSTANCE;

   
public static T14_VolatileSingle getInstance() {

       
if (INSTANCE == null) {
           
//DCL双重检查
           
synchronized (T14_VolatileSingle.class) {
               
if (INSTANCE == null) {
                   
try {
                       
Thread.sleep(1);
                    }
catch (InterruptedException e) {
                       
e.printStackTrace();
                    }
                   
INSTANCE = new T14_VolatileSingle();
                }
            }
        }
       
return INSTANCE;
    }

   
public static void main(String[] args) {
       
for (int i = 0; i < 100000; i++) {
           
new Thread(() -> {
               
System.out.println(T14_VolatileSingle.getInstance().hashCode());
            })
.start();
        }
    }
}

添加volatile的原因,INSTANCE = new T14_VolatileSingle();创建对象的过程分为三步
第一步:给对象申请内存,并赋为初始值

第二步:给对象将值赋为真正的值

第三步:将变量指向对象

 

第三步跟第二步发生指令重排序,此时变量指向的对象已经不是null,但是也不是真正的值,获取此数据直接去使用会有异常,是不正确的。

Volatile会禁止指令重排序,以下程序有volatile没有synchronized也是不正确的,修改后其他线程可见,但是++内部会分很多步执行,其他线程会对相同值进行++后赋值,会比实际的小

Volatile不能替代synchronized,只是保证可见性package com.hy.mashibing2.knowledge;

import java.util.ArrayList;

/**
 *
@author hanyong
 *
@date 2020/9/9 22:33
 */
public class T15_VolatileCanNotReplaceSyn {
  
volatile int  count = 0;

  
synchronized void  m() {
       
for (int i = 0; i < 10000; i++) {
           
count++;
        }
    }

   
public static void main(String[] args) {
       
T15_VolatileCanNotReplaceSyn t = new T15_VolatileCanNotReplaceSyn();
       
ArrayList<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

7.锁其他点

 

7.1细化锁,粗化锁

细化尽可能的锁最少的代码,粗化锁当方法征用频繁的时候粗胡下

package com.hy.mashibing2.knowledge;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 *
细化锁
 
*
 *
@author hanyong
 *
@date 2020/9/9 22:53
 */
public class T16_FineLock {
   
volatile int count = 0;

   
void m() {
       
try {
           
//业务逻辑
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
synchronized (this) {
            
count++;
        }
       
try {
           
//业务逻辑
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
            
e.printStackTrace();
        }
    }

   
public static void main(String[] args) {
       
T16_FineLock t = new T16_FineLock();
       
ArrayList<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

7.2锁同一对象

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/9 23:04
 */
public class T17_SynSameObject {
   
final Object o = new Object();//final防止被重新赋值

   
void m() {
       
synchronized (o) {
           
while (true) {
               
try {
                   
TimeUnit.SECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
               
System.out.println(Thread.currentThread().getName());
            }
        }
    }

   
public static void main(String[] args) {
       
T17_SynSameObject t = new T17_SynSameObject();
       
new Thread(t::m, "thread1").start();
       
new Thread(t::m, "thread2").start();
//        t.o = new Object();//注释掉后thread2不会执行,此处对象变成另一个对象,先执行的线程锁不住第二个线程
   
}
}

8.CAS

8.1AtomicInteger使用案列

 

package com.hy.mashibing2.knowledge;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
@author hanyong
 *
@date 2020/9/9 23:30
 */
public class T18_AtomicInteger {
   
AtomicInteger count=new AtomicInteger(0);

   
void m() {
       
for (int i = 0; i < 1000; i++) {
           
count.incrementAndGet();
        }
    }

   
public static void main(String[] args) {
        
T18_AtomicInteger t = new T18_AtomicInteger();
       
List<Thread> threads = new ArrayList<>();
       
for (int i = 0; i < 10; i++) {
           
threads.add(new Thread(t::m, "thread-" + i));
        }
       
threads.forEach((o) -> o.start());
       
threads.forEach((o) -> {
           
try {
               
o.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        });
       
System.out.println(t.count);
    }
}

8.2原理

内部调用UnsafegetAndAddInt方法

public final int getAndAddInt(Object var1, long var2, int var4) {
   
int var5;
   
do {
       
var5 = this.getIntVolatile(var1, var2);
    }
while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

   
return var5;
}

cas(v,excepted,NewValue); v为之前获得值,e为期待值,n为要设定的新值

if(v==e)

v=new

否则重试。Cascpu原语级别,执行过程不会被打断,也就是不怕其他线程打断出错

ABA问题,解决思路加version

8.3atomic synchronized Longadder性能大比拼

package com.hy.mashibing2.knowledge;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;

/**
 *
@author hanyong
 *
@date 2020/9/10 23:31
 */
public class T19_AtomicvsSynvsLongAdder {

   
static AtomicInteger count1 = new AtomicInteger(0);
   
static long count2 = 0L;
   
static LongAdder count3 = new LongAdder();


   
public static void main(String[] args) {

       
Thread[] threads = new Thread[1000];
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
for (int k = 0; k < 10000; k++) {
                   
count1.incrementAndGet();
                }

            })
;

        }
       
long atomiStartTime = System.currentTimeMillis();
       
for (Thread thread : threads) {
           
thread.start();
        }
       
for (Thread thread : threads) {
           
try {
                
thread.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long atomEndTime = System.currentTimeMillis();
       
System.out.println("AtomicInteger" + count1.get() + "耗时:" + (atomEndTime - atomiStartTime));

       
final Object o = new Object();
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(new Runnable() {
               
@Override
               
public void run() {
                    
for (int k = 0; k < 10000; k++) {
                       
synchronized (o) {
                           
count2++;
                        }
                    }
                }
            })
;
        }
       
long longStartTime = System.currentTimeMillis();
       
for (Thread t : threads) {
           
t.start();
        }
       
for (Thread t : threads) {
           
try {
               
t.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long longEndTime = System.currentTimeMillis();
       
System.out.println("synch" + count2 + "耗时:" + (longEndTime - longStartTime));


       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
for (int k = 0; k < 10000; k++) {
                   
count3.increment();
                }
            })
;
        }

       
long longAddStartTime = System.currentTimeMillis();
       
for (Thread t : threads) {
           
t.start();
        }
       
for (Thread t : threads) {
           
try {
               
t.join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
       
long longAddEndTime = System.currentTimeMillis();
        
System.out.println("LongAdd" + count3.longValue() + "耗时:" + (longAddEndTime - longAddStartTime));
    }

}

输出结果:

AtomicInteger10000000耗时:203

synch10000000耗时:549

LongAdd10000000耗时:135

矩形: 圆角: SumLongAdder线程多时效率最高,原因LongAdder内部会有一个数组,将数字放到数组中,不同部分线程对数组的某个索引值进行递增,最终对数组所有元素进行递增,内部实现也是CAS所以较快。

                   
    文本框: 0
  文本框: 0   文本框: 0   文本框: 0
         
 
 

 

 

 

250个线程对第一个进行递增,250线程对第二个进行递增,。。。最终进行相加得到结果

9.新型锁

9.1reentrantLock可重入性

可重入性,不同线程存在竞争,但是相同线程执行一个方法,当方法内部调用其他加锁方法时,当synch锁的是同一个对象就可以进行调用。可重入性

package com.hy.mashibing2.knowledge;
import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/11 0:31
 */
public class T20_ReentrantLock1 {
   
synchronized void m1() {
       
for (int i = 0; i < 10; i++) {
           
try {
               
TimeUnit.SECONDS.sleep(1);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(i);
           
if(i==2){
               
m2();
            }
        }
    }

   
synchronized void m2() {
       
System.out.println("m2执行了");
    }

   
public static void main(String[] args) {
       
T20_ReentrantLock1 t = new T20_ReentrantLock1();
       
new Thread(t::m1).start();
//        new Thread(t::m2).start();
   
}
}

9.2reentrantLock基本用法

作用同synchronizedTryfinally使用。使用前lock,finally里面unlock

package com.hy.mashibing2.knowledge;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 18:57
 */
public class T21_ReentrantLock2 {

   
ReentrantLock lock = new ReentrantLock();

   
void m1() {
       
try {
            
lock.lock();
           
for (int i = 0; i < 10; i++) {
               
TimeUnit.SECONDS.sleep(1);
               
System.out.println("m" + i);
            }
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
finally {
           
lock.unlock();
        }

    }

   
void m2() {
       
try {
           
lock.lock();
           
System.out.println("m2执行了");
        }
finally {
           
lock.unlock();
        }


    }

   
public static void main(String[] args) {
       
T21_ReentrantLock2 t = new T21_ReentrantLock2();
       
new Thread(t::m1).start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
new Thread(t::m2).start();

    }
}

9.3reentrantLock lock.tryLock案例

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 21:24
 */
public class T23_ReentrantLock3 {
   
ReentrantLock lock = new ReentrantLock();

   
void m1() {
       
try {
           
lock.lock();
           
for (int i = 0; i < 3; i++) {
               
TimeUnit.SECONDS.sleep(1);
               
System.out.println(i);
            }
        }
catch (Exception e) {
           
e.printStackTrace();
        }
finally {
           
lock.unlock();
        }
    }

   
/**
     *
使用tryLock进行尝试锁定,无论锁定与否,方法都会继续执行
    
* 可以根据tryLock的返回值来判断是否锁定
    
* 也可指定tryLock的时间
    
*/
   
void m2() {
       
boolean locked = false;
       
try {
           
//5秒钟之内一直去获得锁,如果获得锁,locked就为true,
           
locked = lock.tryLock(3, TimeUnit.SECONDS);
            
System.out.println("m2方法执行了"+locked);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
finally {
           
if (locked) {
               
lock.unlock();
            }
        }
    }

   
public static void main(String[] args) {
       
T23_ReentrantLock3 t=new T23_ReentrantLock3();
       
new Thread(t::m1).start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
        
new Thread(t::m2).start();
    }
}

9.4 reentrantLock lock.lockInterruptibly可被打断,执行catch块的方法

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/12 23:41
 */
public class T24_ReentrantLock4 {

   
public static void main(String[] args) {
       
ReentrantLock lock = new ReentrantLock();
       
Thread t1=new Thread(()->{
           
try {
               
lock.lock();
               
System.out.println("线程1start");
               
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
               
System.out.println("线程1end");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
lock.unlock();
            }
        },
"线程1");
       
Thread t2=new Thread(()->{
           
try{
               
lock.lockInterruptibly();
               
System.out.println("线程2执行开始");
               
TimeUnit.SECONDS.sleep(5);
               
System.out.println("线程2执行结束");
            }
catch (InterruptedException e) {
               
System.out.println("m2被打断"+e.getMessage());
               
e.printStackTrace();
            }
finally {
               
lock.unlock();
            }
        },
"线程2");
       
t1.start();
       
try {
           
TimeUnit.SECONDS.sleep(1);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
t2.start();

       
t2.interrupt();
    }
}

 

9.5reentrantLock公平锁

一个线程执行完,另一个线程再执行,新加过来的线程进入等待队列,有序队列,排队执行。不会乱序争抢

package com.hy.mashibing2.knowledge;

import java.util.concurrent.locks.ReentrantLock;

/**
 *
@author hanyong
 *
@date 2020/9/13 0:09
 */
public class T25_ReentrantLock5 extends Thread {

   
//公平锁
   
private static ReentrantLock lock = new ReentrantLock(true);

   
@Override
   
public void run() {
       
for (int i = 0; i < 100; i++) {
           
try {
               
lock.lock();
               
System.out.println(Thread.currentThread().getName() + "获得锁");
            }
finally {
                
lock.unlock();
            }
        }
    }

   
public static void main(String[] args) {
       
T25_ReentrantLock5 t = new T25_ReentrantLock5();
       
Thread thread1 = new Thread(t, "线程1");
       
Thread thread2 = new Thread(t, "线程2");
        
thread1.start();
       
thread2.start();
    }
}

打印结果

线程2获得锁

线程1获得锁

线程2获得锁

线程1获得锁

9.6CountDownLatch

package com.hy.mashibing2.knowledge;

import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch
倒数门闩
 
*
 *
@author hanyong
 *
@date 2020/9/14 21:45
 */
public class T26_CountDownLatch1 {

   
public static void main(String[] args) {

    }

   
private static void usingCountDownLatch() {
       
Thread[] threads = new Thread[100];
       
CountDownLatch latch = new CountDownLatch(threads.length);
       
for (int i = 0; i < threads.length; i++) {
           
threads[i] = new Thread(() -> {
               
int result = 0;
               
for (int j = 0; j < 10000; j++) {
                   
result += j;
                   
latch.countDown();
                }
            })
;
        }

       
for (int i = 0; i < threads.length; i++) {
           
threads[i].start();
        }

       
try {
           
latch.await(); //所有的线程latch.countDown();执行完,门闩打开执行后面的代码
       
} catch (InterruptedException e) {
           
e.printStackTrace();
        }
       
System.out.println("end latch");
    }

   
private static void usingJoin() {
       
Thread[] threads = new Thread[100];
       
for (int i = 0; i < threads.length; i++) {
            
threads[i] = new Thread(() -> {
               
int result = 0;
               
for (int j = 0; j < 10000; j++) {
                   
result += j;
                }
            })
;
        }

       
for (int i = 0; i < threads.length; i++) {
            
threads[i].start();
        }

       
for (int i = 0; i < threads.length; i++) {
           
try {
               
threads[i].join();
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
        }
    }

}

9.7CyclicBarrier 栅栏,满后执行

package com.hy.mashibing2.knowledge;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 *
 * CyclicBarrier
栅栏,满了之后做后续动作
 
* @author hanyong
 *
@date 2020/9/14 23:29
 */
public class T27_CyclicBarrier {


    
public static void main(String[] args) {

//        CyclicBarrier barrier = new CyclicBarrier(20);
       
CyclicBarrier barrier = new CyclicBarrier(20,()->{
           
System.out.println("lamda满人发车");
        });
       
/* CyclicBarrier barrier = new CyclicBarrier(20, new Runnable() {
            @Override
            public void run() {
                System.out.println("
人满发车");
            }
        });*/

       
Thread[] threads = new Thread[100];
       
for (int i = 0; i < threads.length; i++) {
            
new Thread(() -> {
               
try {
                   
barrier.await();
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
catch (BrokenBarrierException e) {
                   
e.printStackTrace();
                }
            })
.start();
        }
    }
}

 

9.8Phaser阶段锁

所有线程执行完当前阶段再开始执行下一阶段

phaser.arriveAndAwaitAdvance();

phaser.arriveAndDeregister();

package com.hy.mashibing2.knowledge;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 *
@author hanyong
 *
@date 2020/9/15 0:19
 */
public class T28_Phaser1 {

   
static Random r = new Random();
   
static Phaser phaser = new MarriagePhaser();

   
static void sleep(int nums) {
       
try {
            
TimeUnit.MILLISECONDS.sleep(nums);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
    }

   
public static void main(String[] args) {
       
phaser.bulkRegister(7);
       
for (int i = 0; i < 5; i++) {
            
new Thread(new Persion("p" + i)).start();
        }
       
new Thread(new Persion("新郎")).start();
       
new Thread(new Persion("新娘")).start();
    }

   
static class MarriagePhaser extends Phaser {
       
@Override
       
protected boolean onAdvance(int phase, int registeredParties) {
           
switch (phase) {
               
case 0:
                   
System.out.println("所有人到齐了!" + registeredParties);
                   
System.out.println();
                   
return false;
                
case 1:
                   
System.out.println("所有人吃完了!" + registeredParties);
                   
System.out.println();
                   
return false;
               
case 2:
                   
System.out.println("所有人离开了!" + registeredParties);
                   
System.out.println();
                   
return false;
               
case 3:
                   
System.out.println("婚礼结束!新娘新郎抱抱" + registeredParties);
                   
return true;
               
default:
                    
return true;
            }

        }
    }

   
static class Persion implements Runnable {
       
String name;

       
public Persion(String name) {
           
this.name = name;
        }

      
void arrive() {
           
sleep(1000);
           
System.out.printf("%s 到达现场! \n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void eat() {
           
sleep(1000);
           
System.out.printf("%s 吃完!\n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void leave() {
           
sleep(1000);
           
System.out.printf("%s 离开!\n", name);
           
phaser.arriveAndAwaitAdvance();
        }

       
void hug() {
           
if (name.equals("新郎") || name.equals("新娘")) {
               
sleep(1000);
               
System.out.printf("%s 洞房!\n", name);
               
phaser.arriveAndAwaitAdvance();
            }
else {
               
phaser.arriveAndDeregister();
            }

        }

       
@Override
       
public void run() {

            
arrive();
           
eat();
           
leave();
           
hug();
        }
    }
}

9.9读写锁

static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();
static Lock writeLock = readWriteLock.writeLock();

readLock为共享锁,读线程可以同时执行,writeLock为排他锁,独占执行

案例如下

package com.hy.mashibing2.knowledge;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
@author hanyong
 *
@date 2020/9/15 23:20
 */
public class T29_ReadWriterLock {

   
static int value;
   
static ReentrantLock lock = new ReentrantLock();
   
static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
   
static Lock readLock = readWriteLock.readLock();
   
static Lock writerLock = readWriteLock.writeLock();

   
public static void read(Lock lock) {
       
try {
           
lock.lock();

           
sleep(1);
            
System.out.println(Thread.currentThread().getName() + "读完了");
        }
finally {
           
lock.unlock();

        }
    }

   
public static void writer(Lock lock, int v) {
       
try {
           
lock.lock();

           
sleep(1);
           
value = v;
           
System.out.println(Thread.currentThread().getName() + "写完了");
        }
finally {
           
lock.unlock();

        }
    }

   
public static void main(String[] args) {
       
//创建10个线程读
       
for (int i = 0; i < 10; i++) {
            
new Thread(() -> {
               
read(readLock);
            },
"读线程" + i).start();
        }

       
//创建2个线程写
       
for (int i = 0; i < 2; i++) {
           
new Thread(() -> {
               
writer(writerLock, new Random().nextInt());
            },
"写线程" + i).start();
        }
    }

   
static void sleep(int time) {
       
try {
           
TimeUnit.SECONDS.sleep(time);
        }
catch (InterruptedException e) {
           
e.printStackTrace();
        }
    }
}

 

9.10semaphore信号量

做限流

package com.hy.mashibing2.knowledge;

import java.util.concurrent.Semaphore;

/**
 *
@author hanyong
*
@date 2020/9/16 22:09
 */
public class T30_Semaphore {
   
public static void main(String[] args) {
       
//1表示同时只能有一个线程执行
       
//Semaphore semaphore=new Semaphore(1);
       
Semaphore semaphore=new Semaphore(1,true);//公平锁,队列,线程排队

       
new Thread(()->{

           
try {
               
semaphore.acquire();//阻塞获得,后为0
               
System.out.println("T1 running...");
               
Thread.sleep(200);
               
System.out.println("T1 running...");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
semaphore.release();//释放,后为1
           
}
        },
"t1").start();

       
new Thread(()->{
           
try {
               
semaphore.acquire();
               
System.out.println("T2 running");
               
Thread.sleep(200);
               
System.out.println("T2 running");
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
finally {
               
semaphore.release();
            }
        },
"t2").start();
    }
}

 

9.11Exchanger交换

*/
public class T31_Exchange {

   
static Exchanger<String> exchanger = new Exchanger();

   
public static void main(String[] args) {
       
new Thread(() -> {
           
String s = "t1";
           
try {
              
s= exchanger.exchange(s);//双人游戏交换装备
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(Thread.currentThread().getName() + s);
        },
"线程1").start();
       
new Thread(() -> {
           
String s = "t2";
           
try {
              
s= exchanger.exchange(s);
            }
catch (InterruptedException e) {
               
e.printStackTrace();
            }
           
System.out.println(Thread.currentThread().getName() + s);
        },
"线程2").start();
    }
}

打印结果

线程1t2

线程2t1

9.12LockSupport

package com.hy.mashibing2.knowledge;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 *
 * LockSupport.park();
不用加锁可以暂停线程
 
* LockSupport.unpark(t);可以恢复park的线程继续执行
 
* LockSupport.unpark(t);可以优先于LockSupport.park();执行,这样park的时候可以不用park
 *
 *
内部实现类似于维护一个count,park变为0unpark变为1,变为1线程继续执行,之前已经为1park不停继续执行,再次变为0就停
 
* @author hanyong
 *
@date 2020/9/16 23:49
 */
public class T32_LockSupport {

   
public static void main(String[] args) {
       
Thread t = new Thread(() -> {
           
for (int i = 0; i < 10; i++) {
               
System.out.println(i);
               
if (i == 5) {
                   
LockSupport.park();
                }
               
try {
                   
TimeUnit.SECONDS.sleep(1);
                }
catch (InterruptedException e) {
                   
e.printStackTrace();
                }
            }
        })
;
       
t.start();
       
LockSupport.unpark(t);
       
/*try {
            TimeUnit.SECONDS.sleep(8);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("
主线程睡了8秒了");
        LockSupport.unpark(t);*/
   
}
}

 

 

posted @ 2020-09-17 00:06  yongzhewuwei  阅读(63)  评论(0编辑  收藏  举报