1、Node类是对要访问同步代码的线程的封装,包含了线程本身及其状态叫waitStatus。waitStatus五种状态如下:
SIGNAL 值为-1,当一个节点的状态为SIGNAL时就意味着在等待获取同步状态,前节点是头节点也就是获取同步状态的节点
CANCELLED 值为1、因为超时或者中断,结点会被设置为取消状态,被取消状态的结点不应该去竞争锁,只能保持取消状态不变,不能转换为其他状态。处于这种状态的结点会被踢出队列,被GC回收( 一旦节点状态值为1说明被取消,那么这个节点会从同步队列中删除 )
CONDITION 值为-2、节点在等待队列中、节点线程等待在Condition、当其它线程对Condition调用了singal()方法该节点会从等待队列中移到同步队列中
PROPAGATE 值为-3、表示下一次共享式同步状态获取将会被无条件的被传播下去(读写锁中存在的状态,代表后续还有资源,可以多个线程同时拥有同步状态)
initial 值为0、表示当前没有线程获取锁(初始状态)
2、Node类有两个常量,SHARED和EXCLUSIVE,分别代表共享模式和独占模式
ReentrantLock是Lock的实现类,是一个互斥的同步锁。
ReentrantLock内部自定义了同步器Sync(Sync既实现了AQS,又实现了AOS,而AOS提供了一种互斥锁持有的方式),其实就是加锁的时候通过CAS算法,将线程对象放到一个双向链表中,每次获取锁的时候,看下当前维护的那个线程ID和当前请求的线程ID是否一样,一样就可重入了。
CountDownLatch (倒计时器):CountDownLatch是一个同步工具类,基于AQS,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行.
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CloseDoor {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(5);
CloseDoor closeDoor = new CloseDoor();
new Thread(() -> {
closeDoor.sayBye("Lucy");
countDownLatch.countDown();
}).start();
new Thread(() -> {
closeDoor.sayBye("Bob");
countDownLatch.countDown();
}).start();
new Thread(() -> {
closeDoor.sayBye("Lily");
countDownLatch.countDown();
}).start();
new Thread(() -> {
closeDoor.sayBye("Sam");
countDownLatch.countDown();
}).start();
new Thread(() -> {
closeDoor.sayBye("Gates");
countDownLatch.countDown();
}).start();
//班长锁门
try {
System.out.println("同学离开中");
countDownLatch.await();
System.out.println("班长锁门");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sayBye(String name) {
try {
System.out.println(name + " pack books to bag");
Random random = new Random();
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is gone");
}
}
复制代码
运行结果:
/**
* 热身运动
*/
public class PlayBasketballDemo {
private static final int THREAD_NUM = 6;
private static final Random random = new Random();
public static void main(String[] args) throws InterruptedException {
String[] names = {"王五", "李四", "冯北", "刘青扬", "刘士凯", "薛贵", "赵钱孙"};
// 使用构造方法:public CyclicBarrier(int parties, Runnable barrierAction)
// 参数parties表示一共有多少线程参与这次“活动”,barrierAction是可选的,用来指定当所有线程都完成这些必须的“任务”之后要干的其他事情
CyclicBarrier barrier = new CyclicBarrier(THREAD_NUM , new Runnable() {
@Override
public void run() {
// 最后写完数据的线程,会执行这个任务
System.out.println("/n人都到齐了,开始热身运动/n");
}
});
// 启动5个线程,写数据
for (int i = 0; i < THREAD_NUM; i++) {
if (i < THREAD_NUM - 1) {
Thread t = new Thread(new MyTask(barrier, names[i]), "线程名" + i);
t.start();
} else {
// 最后一个线程延迟3秒执行
Thread.sleep(3000);
Thread t = new Thread(new MyTask(barrier, names[i]));
t.start();
}
}
}
static class MyTask extends Thread {
private CyclicBarrier barrier;
private String name;
public MyTask(CyclicBarrier barrier, String name) {
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
int time = random.nextInt(1000);
System.out.println(name + " 从宿舍出发");
try {
Thread.sleep(time);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(name + " 到达篮球场");
try {
// 用来挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
// 等待所有线程都调用过此函数才能继续后续动作
// 只等待2s,那么最后一个线程3秒才执行,则必定会超时
// barrier.await(2000, TimeUnit.MILLISECONDS);
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(name + " 开始热身");
}
}
}
复制代码
运行结果:
public CyclicBarrier(intparties,RunnablebarrierAction)
Semaphore是基于AQS的共享模式实现的
import java.util.concurrent.Semaphore;
/**
* 吃饭问题
* 现在 N 个人;M双筷子
*/
public class EatNoodles {
private static int PEOPLE_NUM = 8; //人数
private static int CHOPSTICKS_NUM = 5; //筷子个数
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(CHOPSTICKS_NUM);
String[] names = {"Lucy", "Lily", "Tom", "Sam", "Gates", "James", "Kates", "Trump", "Zoe", "Mia"};
for (int i = 0; i < PEOPLE_NUM; i++)
new Worker(names[i], semaphore).start();
}
static class Worker extends Thread {
private String name;
private Semaphore semaphore;
public Worker(String name, Semaphore semaphore) {
this.name = name;
this.semaphore = semaphore;
}
@Override
public void run() {
try {
semaphore.acquire();
System.out.println(this.name + " 占用一双筷子在吃饭...");
Thread.sleep(2000);
System.out.println(this.name + " 吃完饭释放筷子...");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
复制代码
运行结果: