- 29
- 0
我有两个线程,这两个个线程A、B互斥 且 都是批处理形式,所以如果某个线程还没执行完所有数据,那么下一次执行的时候,还是得进入此线程中。并且当有一个接口被调用的时候,如果A,B线程此时都没有数据处理的话,插入数据并且指定B线程执行。
我采用的是两种变量互斥,但是还是会存在相关线程安全问题。所以有没有更好的方法去处理了。
相关代码
线程A:
public class AaHistoryTask extends TimerTask {
@Override
public void run() {
try {
//丑陋的状态控制,如果B线程在数据处理中,退出。
if(AsStatusUtil.getAsSettleRepay()) {
return;
}
boolean hasIdleThreads = false;
List<FactoringsDbCore.AaHistory.Builder> aahs = Db2Pb.toAaHistory(
QueryMethods.queryAaHistory(BATCH_SIZE, null));
if (aahs.size() > 0) {
if (!AsStatusUtil.setAsAah(true)) {
return;
}
logger.info("AaHistoryTask inPutAaHistorySize: " + aahs.size());
} else {
//修改aah状态为false
AsStatusUtil.setAsAah(false);
return;
}
for (FactoringsDbCore.AaHistory.Builder aah : aahs) {
SUB_AA_HISTORY_TASKS[(int) (Long.parseLong(aah.getAccountId()/*.substring(0,17)*/) % SUB_TASK_COUNT)].addNewAah(aah);
}
} catch (Exception e) {
logger.error("", e);
}
}
}
线程B:
public class SettleKeeperTask extends TimerTask {
@Override
public void run() {
try {
//丑陋的状态控制实现,A线程处理数据中,退出
if (AsStatusUtil.getAsAah()) {
return;
}
List<FactoringsDbCore.AccountSum.Builder> ass = Db2Pb.toAccountSum(
QueryMethods.queryAccountSumToBeSettle(BATCH_SIZE, null));
if (ass.size() > 0) {
if(!AsStatusUtil.setAsSettleRepay(true)) {
return;
}
logger.info("SettleKeeperTask settle inPutAccountSumSize: " + ass.size());
//开始
SettleRepayKeeper.settle(ass);
} else {
//开始
List<FactoringsDbCore.Repay.Builder> repayList = Db2Pb.toRepay(
QueryMethods.queryRepay(FactoringsDbBase.RepayStatus.RS_REPAYING, 1, null));
if(repayList.size() > 0) {
if(!AsStatusUtil.setAsSettleRepay(true)) {
return;
}
//全部处理完之后,状态置为false
SettleRepayKeeper.repay(repayList.get(0), BATCH_SIZE);
} else {
AsStatusUtil.setAsSettleRepay(false);
}
}
} catch (Exception e) {
logger.error("", e);
}
}
}
AsStatusUtil类是:
public class AsStatusUtil {
//B线程处理状态,处理中为true,处理完为false
private static boolean asSettleRepay = false;
//A线程处理状态,true表示执行中,false表示未开始或者已完成[默认AAH先处理]
private static boolean asAah = true;
public static synchronized boolean getAsSettleRepay() {
return asSettleRepay;
}
public static synchronized boolean getAsAah() {
return asAah;
}
public static synchronized boolean setAsSettleRepay(boolean flag) {
//如果A正在执行,返回false,无法切换状态
if(asAah) {
return false;
}
asSettleRepay = flag;
return true;
}
public static synchronized boolean setAsAah(boolean flag) {
//如果B正在执行,返回false,无法切换状态
if(asSettleRepay) {
return false;
}
asAah = flag;
return true;
}
} - 共 0 条
- 全部回答
-
雷袭月启 普通会员 1楼
Java线程互斥问题是指在同一时间只有一个线程可以访问共享资源的情况。这通常发生在多线程环境中,比如多线程操作数据库、多线程网络编程等。
解决Java线程互斥问题的方法主要有以下几种:
-
使用synchronized关键字:synchronized关键字可以用来同步一个或多个方法,它保证了在同一时间只有一个线程可以访问共享资源。但是,synchronized关键字的使用并不推荐,因为它会阻塞其他线程,可能会导致程序的运行效率降低。
-
使用wait()和notify()方法:wait()方法会阻塞当前线程,直到有其他线程唤醒它。notify()方法会唤醒一个等待的线程。这两种方法可以用来实现线程的互斥。
-
使用锁:Java中有很多种锁,如ReentrantLock、DiscardingReentrantLock等,它们可以用来实现线程的互斥。但是,使用锁可能会导致过多的锁竞争,因此需要谨慎使用。
-
使用Java的并发包:Java的并发包提供了很多并发相关的类和方法,如ConcurrentHashMap、ConcurrentQueue等,它们可以用来实现线程的互斥。
-
使用Java的多线程库:Java的多线程库,如JavaFX、JavaFXFX、Swing等,它们提供了一些线程控制的类和方法,可以用来实现线程的互斥。
以上就是Java线程互斥问题的一些解决方法,具体的使用方法需要根据实际的需求来选择。
-
- 扫一扫访问手机版
回答动态

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器更新之后。服务器里面有部分玩家要重新创建角色是怎么回事啊?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题函数计算不同地域的是不能用内网吧?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题ARMS可以创建多个应用嘛?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题在ARMS如何申请加入公测呀?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题前端小程序接入这个arms具体是如何接入监控的,这个init方法在哪里进行添加?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器刚到期,是不是就不能再导出存档了呢?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器的游戏版本不兼容 尝试更新怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器服务器升级以后 就链接不上了,怎么办?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器转移以后服务器进不去了,怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器修改参数后游戏进入不了,是什么情况?预计能赚取 0积分收益
- 回到顶部
- 回到顶部
