6 changed files with 265 additions and 21 deletions
-
29src/main/java/com/iflytop/colortitration/app/controller/CraftsController.java
-
148src/main/java/com/iflytop/colortitration/app/core/crafts/CraftsDispatcher.java
-
32src/main/java/com/iflytop/colortitration/app/core/crafts/CraftsJob.java
-
15src/main/java/com/iflytop/colortitration/app/core/state/DeviceState.java
-
2src/main/java/com/iflytop/colortitration/app/service/DeviceCommandService.java
-
60src/main/java/com/iflytop/colortitration/common/service/CraftsService.java
@ -0,0 +1,148 @@ |
|||
package com.iflytop.colortitration.app.core.crafts; |
|||
|
|||
import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; |
|||
import com.iflytop.colortitration.app.core.state.DeviceState; |
|||
import jakarta.annotation.PostConstruct; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.concurrent.BlockingQueue; |
|||
import java.util.concurrent.ExecutorService; |
|||
import java.util.concurrent.Executors; |
|||
import java.util.concurrent.LinkedBlockingQueue; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
import java.util.concurrent.locks.Condition; |
|||
import java.util.concurrent.locks.ReentrantLock; |
|||
|
|||
/** |
|||
* 动态为每个滴定位模块创建独立队列和工作线程 |
|||
*/ |
|||
@Slf4j |
|||
@Component |
|||
@RequiredArgsConstructor |
|||
public class CraftsDispatcher { |
|||
private final BlockingQueue<CraftsJob> jobQueue = new LinkedBlockingQueue<>(); |
|||
private ExecutorService executor; |
|||
private final AtomicInteger threadCounter = new AtomicInteger(0); |
|||
private final ReentrantLock pauseLock = new ReentrantLock(); |
|||
private final Condition pauseCondition = pauseLock.newCondition(); |
|||
private final DeviceState deviceState; |
|||
|
|||
@PostConstruct |
|||
public void init() { |
|||
MultipleModuleCode[] modules = MultipleModuleCode.values(); |
|||
int totalThreads = modules.length; |
|||
executor = Executors.newFixedThreadPool(totalThreads, r -> { |
|||
int id = threadCounter.incrementAndGet(); |
|||
return new Thread(r, "CraftsWorker-" + id); |
|||
}); |
|||
for (int i = 0; i < totalThreads; i++) { |
|||
executor.submit(createWorker()); |
|||
} |
|||
log.info("已初始化{}个工作线程来处理滴定任务。", totalThreads); |
|||
} |
|||
|
|||
/** |
|||
* 创建消费线程,每个线程从队列中取任务并执行 |
|||
*/ |
|||
private Runnable createWorker() { |
|||
return () -> { |
|||
while (true) { |
|||
try { |
|||
CraftsJob job = jobQueue.take(); |
|||
job.executeSteps(this); |
|||
log.info("试管编号 {} 的任务执行成功。", job.getTubeNum()); |
|||
} catch (InterruptedException e) { |
|||
Thread.currentThread().interrupt(); |
|||
log.warn("工作线程被中断,停止执行。"); |
|||
return; |
|||
} catch (Exception e) { |
|||
log.error("处理任务时发生错误: {}", e.getMessage(), e); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* 将新的待执行工艺添加至队列 |
|||
*/ |
|||
public void addCraftsJob(CraftsJob craftsJob) { |
|||
try { |
|||
jobQueue.put(craftsJob); |
|||
log.info("试管编号 {} 的任务已添加到队列中。", craftsJob.getTubeNum()); |
|||
} catch (InterruptedException e) { |
|||
Thread.currentThread().interrupt(); |
|||
log.error("添加试管编号 {} 的任务时发生中断。", craftsJob.getTubeNum()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取所有待执行的任务 |
|||
*/ |
|||
public BlockingQueue<CraftsJob> getAllJobs() { |
|||
return jobQueue; |
|||
} |
|||
|
|||
/** |
|||
* 根据试管编号删除任务 |
|||
*/ |
|||
public void removeCraftsJob(int tubeNum) { |
|||
boolean removed = false; |
|||
for (CraftsJob job : jobQueue) { |
|||
if (job.getTubeNum() == tubeNum) { |
|||
jobQueue.remove(job); // 删除任务 |
|||
removed = true; |
|||
log.info("试管编号 {} 的任务已从队列中删除。", tubeNum); |
|||
} |
|||
} |
|||
if (!removed) { |
|||
log.warn("未找到试管编号 {} 的任务进行删除。", tubeNum); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 如果暂停,线程将进入等待状态 |
|||
* |
|||
* @throws InterruptedException 如果线程被中断 |
|||
*/ |
|||
public void waitIfPaused() throws InterruptedException { |
|||
pauseLock.lock(); |
|||
try { |
|||
while (deviceState.isPaused()) { |
|||
// 如果已暂停,当前线程将被挂起,直到调用 notifyAll() 唤醒 |
|||
pauseCondition.await(); |
|||
} |
|||
} finally { |
|||
pauseLock.unlock(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 暂停所有任务 |
|||
*/ |
|||
public void pause() { |
|||
pauseLock.lock(); |
|||
try { |
|||
deviceState.setPaused(true); |
|||
log.info("所有任务已暂停。"); |
|||
} finally { |
|||
pauseLock.unlock(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 恢复所有任务 |
|||
*/ |
|||
public void resume() { |
|||
pauseLock.lock(); |
|||
try { |
|||
deviceState.setPaused(false); |
|||
pauseCondition.signalAll(); // 唤醒所有等待的线程 |
|||
log.info("所有任务已恢复。"); |
|||
} finally { |
|||
pauseLock.unlock(); |
|||
} |
|||
} |
|||
|
|||
} |
@ -0,0 +1,32 @@ |
|||
package com.iflytop.colortitration.app.core.crafts; |
|||
|
|||
import com.iflytop.colortitration.app.common.enums.MultipleModuleCode; |
|||
import com.iflytop.colortitration.common.model.entity.Crafts; |
|||
import lombok.Data; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.config.ConfigurableBeanFactory; |
|||
import org.springframework.context.annotation.Scope; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) |
|||
@Data |
|||
public class CraftsJob { |
|||
private int tubeNum; |
|||
private List<MultipleModuleCode> selectedModules; |
|||
private Crafts crafts; |
|||
|
|||
public void executeSteps(CraftsDispatcher dispatcher) { |
|||
log.info("执行工艺开始,试管{}", tubeNum); |
|||
try { |
|||
Thread.sleep(1000); |
|||
} catch (InterruptedException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
log.info("执行工艺结束,试管{}", tubeNum); |
|||
} |
|||
|
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue