这里写目录标题
ReentrantLock 也是CAS
ReentrantLock 支持公平锁和非公平锁,可重入锁 ReentrantLock的底层是通过 AQS 实现。可以替代sync
lock(); unlock(); 加锁与释放锁
package msb.reentranlockp;
import msb.commons.ThreadUtil;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class T01_ReentrantLock2 {
Lock lock=new ReentrantLock();
public void m(){
try {
lock.lock();
ThreadUtil.threadSleep(1000);
System.out.println(Thread.currentThread().getName());
}finally {
lock.unlock();
}
}
public void m2(){
try {
lock.lock();
ThreadUtil.threadSleep(1000);
System.out.println(Thread.currentThread().getName());
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
T01_ReentrantLock2 r = new T01_ReentrantLock2();
new Thread(r::m).start();
new Thread(r::m2).start();
}
}
必须使用 unlock 进行释放锁,一般结合 try {}finally { lock.unlock(); } 进行使用,
尝试锁定,
就是尝试去拿锁,进行锁定,不管锁定与否,方法都将继续执行
可以根据 tryLock 的返回直接来判断是否锁定
也可以指定 tryLock 的时间,由tryLock (time) 抛出异常,所以要注意 unlock 的释放
package msb.reentranlockp;
import msb.commons.ThreadUtil;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class T01_ReentrantLock3 {
Lock lock=new ReentrantLock();
public void m(){
lock.lock();
for (int i = 0; i < 9; i++) {
ThreadUtil.threadSleep(1000);
System.out.println(Thread.currentThread().getName());
}
lock.unlock();
}
public void m2(){
try {
// 尝试5秒之内拿到锁,返回true 就是拿到,返回false 就是没拿到
// 无论返回什么,都不影响代码继续运行,
boolean b = lock.tryLock(5, TimeUnit.SECONDS);
// boolean b = lock.tryLock( );//没有时间执行代码,就会立即去尝试获取锁
System.out.println(b);
lock.unlock();// 如果不是放锁,其他线程就拿不到锁,
// 如果没拿到锁,还要执行释放锁 代码异常java.lang.IllegalMonitorStateException
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
T01_ReentrantLock3 r = new T01_ReentrantLock3();
new Thread(r::m).start();
ThreadUtil.threadSleep(1000);
new Thread(r::m2).start();
ThreadUtil.threadSleep(1000);
new Thread(r::m).start();
}
}
可被打断的锁 lockInterruptibly
睡眠的线程不能被打断,可以打断长时间因为获取不到锁 ,而在等待的线程, 被加锁正在运行的线程是无法打断的
package msb.reentranlockp;
import msb.commons.ThreadUtil;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 可被打断的锁
*/
public class T01_ReentrantLock4 {
static Lock lock=new ReentrantLock();
public void m(){
lock.lockInterruptibly();
for (int i = 0; i < 9; i++) {
// 测试时间过长
ThreadUtil.threadSleepF(30);
System.out.println(Thread.currentThread().getName());
}
lock.unlock();
}
public void m2(){
try {
lock.lockInterruptibly();//可被中断的锁
System.out.println("调用线程t2.interrupt();,我被中断了");
System.out.println("调用线程t2.interrupt(),我被中断了");
System.out.println("调用线程t2.interrupt(),我被中断了");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
T01_ReentrantLock4 r = new T01_ReentrantLock4();
Thread thread = new Thread(r::m);
thread.start();
ThreadUtil.threadSleep(1000);
System.out.println("进行打断线程1");
thread.interrupt();
System.out.println("启动m2线程");
Thread t2 = new Thread(r::m2);
t2.start();
//等待3秒进行打断
ThreadUtil.threadSleep(3000);
System.out.println("进行打断");
t2.interrupt();// 线程调用 进行中断获取锁,获取不到锁,就中断,不用等待了
ThreadUtil.threadSleep(1000);
}
}
公平锁和非公平锁
公平: 其他线程获取锁去等待队列里面排队
非公平:其他线程获取锁直接去抢锁
package msb.reentranlockp;
import msb.commons.ThreadUtil;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 公平锁和非公平锁
*/
public class T01_ReentrantLock5 {
static Lock lock = new ReentrantLock( );
public void m() {
try {
for (int i = 0; i < 1000; i++) {
lock.lock();
System.out.println(Thread.currentThread().getName());
lock.unlock();
}
} catch ( Exception e) {
e.printStackTrace();
lock.unlock();
}
}
public static void main(String[] args) {
T01_ReentrantLock5 r = new T01_ReentrantLock5();
Thread t1 = new Thread(r::m);
Thread t2 = new Thread(r::m);
t1.start();
t2.start();
}
}
CountDownLatch 门栓
package msb.countdown;
import java.util.concurrent.CountDownLatch;
/**
* CountDownLatch
* 门栓
*/
public class CountDown {
public static void main(String[] args) {
usingCountDownLatch();
}
private static void usingCountDownLatch(){
Thread [] threads = new Thread[100];//定义100个线程
CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
//CountDownLatch latch = new CountDownLatch(200);//定义一个数量,
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();//每个线程创建完成, latch-1
// latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();//启动线程
}
try {
latch.await(); //线程等待.等待latch 数到0 继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
如果定义200,循环 100个线程,代码是不会输出end,不会停止,
如果定义小于100,则会提前输出吧,
如果每次调用两次 latch.countDown(); 每次则减少2
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();//每个线程创建完成, latch-1
// latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
});
}
package msb.countdown;
import java.util.concurrent.CountDownLatch;
/**
* CountDownLatch
* 门栓
*/
public class CountDown {
public static void main(String[] args) {
// usingCountDownLatch();
usjoin();
}
private static void usingCountDownLatch(){
Thread [] threads = new Thread[100];//定义100个线程
CountDownLatch latch = new CountDownLatch(threads.length);//定义一个数量,
//CountDownLatch latch = new CountDownLatch(200);//定义一个数量,
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(()->{
int result = 0;
for (int j = 0; j < 100; j++) {
result +=j;
}
latch.countDown();//每个线程创建完成, latch-1
// latch.countDown();//每个线程创建完成, latch -1 可以多次调用 .,每次都是减一
});
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();//启动线程
}
try {
latch.await(); //线程等待.等待latch 数到0 继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end");
}
private static void usjoin(){
Thread [] threads=new Thread[100];
for (int i = 0; i < threads.length; i++) {
threads[i] =new Thread(()->{
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getName());
}
});
}
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();
}
}
System.out.println(Thread.currentThread().getName());
}
}
CyclicBarrier
package msb.cyc;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 栅栏
*/
public class T01_CyclicBarrier {
public static void main(String[] args) {
CyclicBarrier barrier= new CyclicBarrier(20)
//指定多少个线程.执行第二个方法
CyclicBarrier barrier= new CyclicBarrier(20,new Runnable(){
@Override
public void run() {
System.out.println("满人,发车");
}
});
for (int i = 0; i < 100; i++) {
// 如果显示线程101循环,只会输出五次,第101个线程,一直等剩余的19个到齐,还会执行
new Thread(()->{
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
满人,发车
满人,发车
满人,发车
满人,发车
满人,发车
读写锁 (共享锁,排它锁)
读锁:共享锁
写锁:排他锁
package msb.readwritelock;
import msb.commons.ThreadUtil;
import msb.where.T01_WhereIsThread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class T01_ReadWriteLock {
static ReentrantLock lock=new ReentrantLock();
static ReadWriteLock readWriteLock= new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();
static Lock write = readWriteLock.writeLock();
public static void read(Lock lock){
lock.lock();
ThreadUtil.threadSleep(1000);
System.out.println("reading");
lock.unlock();
}
public static void write(Lock lock,int value){
lock.lock();
ThreadUtil.threadSleep(1000);
System.out.println("write");
lock.unlock();
}
public static void main(String[] args) {
Runnable readR = ()->read(lock); // 如果使用lock 锁 每个都是获取一把锁
// Runnable readR = ()->read(readLock); // 使用读锁.可以共享
Runnable writeW = ()->write(lock,3); // 使用写锁,是单独的一把锁,不释放,其他线程没办法执行
// Runnable writeW = ()->write(write,3);
for (int i = 0; i <18 ; i++) {
new Thread(readR).start();
}
for (int i = 0; i <2 ; i++) {
new Thread(writeW).start();
}
}
}
Semaphore
通行证,买票
package msb.semaphore;
import msb.commons.ThreadUtil;
import java.util.concurrent.Semaphore;
public class T01_SemaPhore {
static Semaphore s = new Semaphore(2);//
// static Semaphore s = new Semaphore(1,true);// 公平锁
public static void main(String[] args) {
new Thread(()->{
try {
s.acquire(4);// 拿到一个通行证
// s.acquire(n);// 拿到一个通行证 如果只有2个通行证,想要获取两个以上,就会一直等待获取.程序不会向下运行,但是其他线程满足获取的通行证就可以进行运行
System.out.println("r1");
ThreadUtil.threadSleep(800);
System.out.println("r1");
s.release(4);
// s.release(x);//释放一个通行证
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
s.acquire(2);
System.out.println("r2");
ThreadUtil.threadSleep(800);
System.out.println("r2");
s.release(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
ExChange 交换
两个线程进行交换
如果另外一个线程不进行exchange 的话,就一直等待另个一个线程交换 (给你换东西,你必须给我一个.要不然不罢休)。
都是两两线程进行交换
package msb.exchange;
import java.util.concurrent.Exchanger;
public class T01_Exchange {
static Exchanger<String> e = new Exchanger<>();
public static void main(String[] args) {
new Thread(()->{
String s="name";
try {
s= e.exchange( s);
System.out.println(s +" " + Thread.currentThread().getName());
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
},"T1").start();
// new Thread(()->{
//
// String s="age";
// try {
// s= e.exchange( s);
// System.out.println(s +" " + Thread.currentThread().getName());
// } catch (InterruptedException interruptedException) {
// interruptedException.printStackTrace();
// }
// },"T2").start();
String s="age";
try {
s= e.exchange( s);
System.out.println(s +" " + Thread.currentThread().getName());
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
四线程进行交换,奇数线程进行交换的话,肯定是有一个线程在等待另外一个线程在等待
package msb.exchange;
import java.util.concurrent.Exchanger;
public class T01_Exchange {
static Exchanger<String> e = new Exchanger<>();
public static void main(String[] args) {
new Thread(()->{
String s="我是t1";
try {
s= e.exchange( s);
System.out.println( Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
},"T1").start();
new Thread(()->{
String s="我是t2";
try {
s= e.exchange( s);
System.out.println( Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
},"T2").start();
new Thread(()->{
String s="我是t3";
try {
s= e.exchange( s);
System.out.println( Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
},"T3").start();
String s="我是mian";
try {
s= e.exchange( s);
System.out.println( Thread.currentThread().getName() +"线程,交换的内容是:"+ s);
} catch ( Exception interruptedException) {
interruptedException.printStackTrace();
}
}
}