账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    Java线程互斥问题
    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
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 雷袭月启 普通会员 1楼

      Java线程互斥问题是指在同一时间只有一个线程可以访问共享资源的情况。这通常发生在多线程环境中,比如多线程操作数据库、多线程网络编程等。

      解决Java线程互斥问题的方法主要有以下几种:

      1. 使用synchronized关键字:synchronized关键字可以用来同步一个或多个方法,它保证了在同一时间只有一个线程可以访问共享资源。但是,synchronized关键字的使用并不推荐,因为它会阻塞其他线程,可能会导致程序的运行效率降低。

      2. 使用wait()和notify()方法:wait()方法会阻塞当前线程,直到有其他线程唤醒它。notify()方法会唤醒一个等待的线程。这两种方法可以用来实现线程的互斥。

      3. 使用锁:Java中有很多种锁,如ReentrantLock、DiscardingReentrantLock等,它们可以用来实现线程的互斥。但是,使用锁可能会导致过多的锁竞争,因此需要谨慎使用。

      4. 使用Java的并发包:Java的并发包提供了很多并发相关的类和方法,如ConcurrentHashMap、ConcurrentQueue等,它们可以用来实现线程的互斥。

      5. 使用Java的多线程库:Java的多线程库,如JavaFX、JavaFXFX、Swing等,它们提供了一些线程控制的类和方法,可以用来实现线程的互斥。

      以上就是Java线程互斥问题的一些解决方法,具体的使用方法需要根据实际的需求来选择。

    更多回答
    网站公告
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部