반응형
java 배치 소스 이렇게 해야지
# DB
oracle.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
oracle.username=hoho
oracle.password=hoho
# 스케줄 (분 단위)
schedule.interval.minute=1
# 동시 프로시저 최대 개수
worker.pool.size=5
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.InputStream;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class Main {
private static final Logger logger = LogManager.getLogger(Main.class);
private static final Properties props = new Properties();
private static String URL;
private static String USER;
private static String PWD;
private static int SCHEDULE_MIN;
private static int WORKER_POOL_SIZE;
private static ScheduledExecutorService scheduler;
private static ExecutorService workerPool;
// ===== 프로시저 관리 =====
static class ProcTask {
String name;
String sql;
AtomicBoolean running = new AtomicBoolean(false);
ProcTask(String name, String sql) {
this.name = name;
this.sql = sql;
}
}
// ===== 프로시저 목록 =====
private static final List<ProcTask> PROC_LIST = Arrays.asList(
new ProcTask("PROC_A", "{ call PROC_DELAY_2MIN() }"),
new ProcTask("PROC_B", "{ call PROC_DELAY_2MIN_2() }"),
new ProcTask("PROC_C", "{ call PROC_DELAY_2MIN_3() }")
);
public static void main(String[] args) {
loadProperties();
initExecutors();
logger.info("배치 스케줄러 시작 ({}분 주기)", SCHEDULE_MIN);
scheduler.scheduleAtFixedRate(
Main::runAllProcedures,
0,
SCHEDULE_MIN,
TimeUnit.MINUTES
);
keepAlive();
}
// ===== properties 로드 =====
private static void loadProperties() {
try (InputStream in = Main.class.getClassLoader().getResourceAsStream("db.properties")) {
if (in == null) throw new RuntimeException("db.properties 파일 없음");
props.load(in);
URL = props.getProperty("oracle.url");
USER = props.getProperty("oracle.username");
PWD = props.getProperty("oracle.password");
SCHEDULE_MIN = Integer.parseInt(props.getProperty("schedule.interval.minute", "1"));
WORKER_POOL_SIZE = Integer.parseInt(props.getProperty("worker.pool.size", "5"));
} catch (Exception e) {
throw new RuntimeException("db.properties 로드 실패", e);
}
}
private static void initExecutors() {
scheduler = Executors.newSingleThreadScheduledExecutor();
workerPool = Executors.newFixedThreadPool(WORKER_POOL_SIZE);
}
// ===== 스케줄 실행 =====
private static void runAllProcedures() {
logger.info("스케줄 실행: {}", LocalDateTime.now());
for (ProcTask proc : PROC_LIST) {
workerPool.submit(() -> executeProcedure(proc));
}
}
// ===== 프로시저 실행 =====
private static void executeProcedure(ProcTask proc) {
if (!proc.running.compareAndSet(false, true)) {
logger.warn("프로시저 {} 실행중 → 스킵", proc.name);
return;
}
long start = System.currentTimeMillis();
logger.info("프로시저 {} 시작", proc.name);
try (Connection conn = getConnection();
CallableStatement stmt = conn.prepareCall(proc.sql)) {
conn.setAutoCommit(true);
stmt.execute();
long sec = (System.currentTimeMillis() - start) / 1000;
logger.info("프로시저 {} 완료 ({}초)", proc.name, sec);
} catch (Exception e) {
logger.error("프로시저 {} 실패", proc.name, e);
} finally {
proc.running.set(false);
}
}
private static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PWD);
}
private static void keepAlive() {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException ignored) {}
}
}
반응형
'dev > java 배포' 카테고리의 다른 글
| java 실행 jar 배포 에러 #011 (0) | 2025.05.08 |
|---|---|
| java batch scheduler #010 (0) | 2025.05.06 |
| java Mssql to Oracle #009 (0) | 2025.05.06 |
| java mssql to file #008 (0) | 2025.05.06 |
| java file read db 저장 #007 (0) | 2025.05.01 |