Active Object(活动对象)
用于实现异步服务对象。它将传统的同步方法调用转换为异步消息传递。
目的:提高系统的并发性和响应性,通过解耦调用者和实际执行者来简化 多线程编程。
一.简单案例
Command Interface
定义了所有可以被异步调用的方法。
interface CalculatorCommand {
int execute();
}
Command Class
包含具体的方法实现,并封装成对象以便异步执行。
class AddCommand implements CalculatorCommand {
private final int a, b;
public AddCommand(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public int execute() {
return a + b;
}
}
Invoker
负责接收客户端请求并创建 Command 对象。
将 Command 对象提交给执行器进行异步处理。
Executor
实际执行 Command 对象的地方,通常是一个线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CalculatorInvoker {
private final ExecutorService executor;
public CalculatorInvoker() {
this.executor = Executors.newFixedThreadPool(10);
}
public void submit(CalculatorCommand command) {
executor.submit(command);
}
}
Client
通过 Invoker 发送请求,并不等待结果返回。
public class Main {
public static void main(String[] args) {
CalculatorInvoker invoker = new CalculatorInvoker();
// 异步执行加法操作
invoker.submit(new AddCommand(10, 20));
}
}
Result Handler (可选)
处理异步执行后返回的结果。
二.完善的
orc兽人/妖魔
public abstract class ActiveCreature {
private static final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());
private BlockingQueue<Runnable> requests;
private String name;
private Thread thread; // Thread of execution.
private int status; // status of the thread of execution.
/**
* Constructor and initialization.
*/
protected ActiveCreature(String name) {
this.name = name;
this.status = 0;
this.requests = new LinkedBlockingQueue<>();
thread = new Thread(() -> {
boolean infinite = true;
while (infinite) {
try {
requests.take().run();
} catch (InterruptedException e) {
if (this.status != 0) {
logger.error("Thread was interrupted. --> {}", e.getMessage());
}
infinite = false;
Thread.currentThread().interrupt();
}
}
});
thread.start();
}
/**
* Eats the porridge.
* @throws InterruptedException due to firing a new Runnable.
*/
public void eat() throws InterruptedException {
requests.put(() -> {
logger.info("{} is eating!", name());
logger.info("{} has finished eating!", name());
});
}
/**
* Roam the wastelands.
* @throws InterruptedException due to firing a new Runnable.
*/
public void roam() throws InterruptedException {
requests.put(() ->
logger.info("{} has started to roam in the wastelands.", name())
);
}
/**
* Returns the name of the creature.
* @return the name of the creature.
*/
public String name() {
return this.name;
}
/**
* Kills the thread of execution.
* @param status of the thread of execution. 0 == OK, the rest is logging an error.
*/
public void kill(int status) {
this.status = status;
this.thread.interrupt();
}
/**
* Returns the status of the thread of execution.
* @return the status of the thread of execution.
*/
public int getStatus() {
return this.status;
}
}
public class Orc extends ActiveCreature {
public Orc(String name) {
super(name);
}
}
public class App implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(App.class.getName());
private static final int NUM_CREATURES = 3;
/**
* Program entry point.
*
* @param args command line arguments.
*/
public static void main(String[] args) {
var app = new App();
app.run();
}
@Override
public void run() {
List<ActiveCreature> creatures = new ArrayList<>();
try {
for (int i = 0; i < NUM_CREATURES; i++) {
creatures.add(new Orc(Orc.class.getSimpleName() + i));
creatures.get(i).eat();
creatures.get(i).roam();
}
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.error(e.getMessage());
Thread.currentThread().interrupt();
} finally {
for (int i = 0; i < NUM_CREATURES; i++) {
creatures.get(i).kill(0);
}
}
}
}