其实前不久,我在工作中也遇到了一个对象池的需求。所谓对象池呢,指的是一次性创建出 N 个对象,之后所有的线程重复利用这 N 个对象,当然对象在被释放前,也是不允许其他线程使用的。对象池,可以用 List 保存实例对象,这个很简单。但关键是限流器的设计,这里的限流,指的是不允许多于 N 个线程同时进入临界区。那如何快速实现一个这样的限流器呢?这种场景,我立刻就想到了信号量的解决方案。
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
public class User {
private String username;
private Integer age;
@Override
public String toString() {
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "User [username=" + username + ", age=" + age + "]";
}
}
import java.util.List;
import java.util.Vector;
import java.util.concurrent.Semaphore;
public class ObjPool {
final List<User> pool;
// 用信号量实现限流器 final Semaphore
final Semaphore sem;
public ObjPool(User... users) {
pool = new Vector<User>();
for (User user : users) {
pool.add(user);
}
System.out.println(users.length);
sem = new Semaphore(users.length);
}
public User remove() {
try {
sem.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
User user = pool.remove(0);
return user;
}
public void add(User user) {
pool.add(user);
sem.release();
}
}
测试
package com.example.lua.demo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Test {
public static void main(String[] args) throws Exception {
User user1 = new User("u1", 1);
User user2 = new User("u2", 2);
User user3 = new User("u3", 3);
ObjPool objPool = new ObjPool(user1, user2, user3);
for(int i = 0; i < 100; i++) {
new Thread(()->{
User user = objPool.remove();
String string = user.toString();
log.info(string);
objPool.add(user);
}).start();
}
}
}