import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class Test6 {
public static void main(String[] args) {
//test1();
test2();
}
private static void test2() {
for (int i = 0; i < 3; i++) {
new People().start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (Integer id : Mailboxes.getIds()) {
new Postman(id,"内容"+id).start();
}
}
/**
* 保护性暂停模式
*/
private static void test1() {
GuardedObject guardedObject = new GuardedObject(12);
//线程1等待线程2的结果
new Thread(() -> {
//等待结果
log.info("等待结果");
Object o = guardedObject.get(1000);
log.info("返回结果是:{}",o);
},"t1").start();
new Thread(() -> {
//执行任务
log.info("执行任务");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//返回结果
guardedObject.complete("answer");
},"t2").start();
}
/**
* blocked 是等待锁的状态
* waiting 是等待被唤醒的状态,唤醒后会重新进入entryList竞争锁
*
* object类的方法,必须是持锁的线程才能调用
* wait
* notify
* notifyAll
*/
}
class GuardedObject{
public GuardedObject(int id) {
this.id = id;
}
private int id;
public int getId() {
return id;
}
//结果
private Object response;
//获取结果
public Object get(long timeout) {
synchronized (this) {
// 开始时间
long begin = System.currentTimeMillis();
//经历的时间
long passTime = 0;
while (response == null) {
//应该等待的时间
long waitTime = timeout - passTime;
//经历的时间超过了最大等待时间,退出循环
if (waitTime<=0) {
break;
}
try {
this.wait(waitTime); //虚假唤醒的问题
} catch (InterruptedException e) {
e.printStackTrace();
}
passTime = System.currentTimeMillis()-begin;
}
return response;
}
}
//产生结果
public void complete(Object response) {
synchronized (this) {
this.response = response;
this.notifyAll();
}
}
}
@Slf4j
class People extends Thread{
@Override
public void run() {
//收信
GuardedObject guardedObject = Mailboxes.createGuardedObject();
log.info("收信:{}",guardedObject.getId());
Object mail = guardedObject.get(5000);
log.info("收到信:{},内容为:{}",guardedObject.getId(),mail);
}
}
@Slf4j
class Postman extends Thread {
private int id ;
private String mail;
public Postman(int id, String mail) {
this.id = id;
this.mail = mail;
}
@Override
public void run() {
log.info("送信id:{} , 内容:{}",id,mail);
Mailboxes.getGuardedObject(id).complete(mail);
}
}
class Mailboxes{
private static Map<Integer, GuardedObject> boxes = new ConcurrentHashMap<>();
private static int id = 1;
public static synchronized int generateId() {
return id++;
}
public static GuardedObject createGuardedObject() {
GuardedObject go = new GuardedObject(generateId());
boxes.put(go.getId(), go);
return go;
}
public static Set<Integer> getIds() {
return boxes.keySet();
}
public static GuardedObject getGuardedObject(int id) {
return boxes.remove(id);
}
}