多线程编程之理财 博客分类: 线程 java多线程理财生产者消费者
程序员文章站
2024-03-24 20:33:40
...
现实生活中,我们一边工作,一边消费,正常情况下会把多余的钱存起来,比如存到余额宝,还可以多挣点钱,现在就有这个情况:我每月可以发工资20000万元 (暂定每月的1号),每月消费5000(租房+生活费)元(暂定每月的1号),其中租金是大头占90%,交房租的方式可以选择(一月一交,两月一交、三月一交),理财:1万元存余额宝一天可以赚1元钱,想知道半年后的理财情况,选择哪种交房租的方式更省钱,具体省多少?
问题分析:这个问题属于于生产者—消费者模型,其中生产者—发工资+理财,消费者—交房租+生活费,其中银行账户作为储存容器,只不过这里跟普通的生产者—消费者模型不一样的是生产者和消费者的动作是指定的,因为日期是定下来的,那来吧直接动手实现吧!
package pc.d3; import java.util.Calendar; import java.util.Date; import util.DateUtils; /** * 日期对象 */ public class DateConstant { /**开始日期,默认是从2015-7-1开始 **/ private static Date nowDate = DateUtils.parseDate("2015-7-1"); public static Date getNowDate() { return nowDate; } public static String getNowDateForString(){ return DateUtils.formatTimestamp(getNowDate()); } /** * 表针走动 */ public static void timeRun(){ nowDate = DateUtils.addSecond(nowDate, 10); } public static boolean isEnd(){ Calendar calendar = Calendar.getInstance(); calendar.setTime(nowDate); //判断是否2015年12月31日 if(calendar.get(Calendar.YEAR)==2016){ return true; } return false; } }
package pc.d3; import org.apache.log4j.Logger; /** * 银行账户 */ public class Account { Logger logger = Logger.getLogger(Producer.class); /**账户金额,默认是0元 **/ private float allMoney = 0; public float getMoney(){ return allMoney; } /** * 消费 * @param money */ public boolean subMoney(float money){ if(money==0){ logger.info(DateConstant.getNowDateForString()+"取钱:银行账户没有钱,好穷啊"); return false; } float sourceMoney = allMoney; allMoney = allMoney - money; logger.info(DateConstant.getNowDateForString()+"取钱:"+sourceMoney+"-"+money+"="+allMoney); return true; } /** * 存钱 */ public boolean addMoney(float money){ if(DateConstant.isEnd()){//结束了 logger.info("-------已结束!-------"); return false; } float sourceMoney = allMoney; allMoney = allMoney + money; logger.info(DateConstant.getNowDateForString()+"存钱:"+sourceMoney+"+"+money+"="+allMoney); return true; } }
package pc.d3; import java.util.Calendar; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; /** * 生产者---往银行账户加钱(主要来自工作的薪水、理财赚的钱) * 其中:1)薪水每月18000元 * 2)理财日收益率: 1/10000 (即1万元一天收益1元) * @author zhoufy */ public class Producer implements Runnable{ Logger logger = Logger.getLogger(Producer.class); /**发工资记录**/ private Set<String> recordPaySet = new HashSet<String>(); private String yearMonth = ""; /**利息结算记录**/ private Set<String> recordInterestSet = new HashSet<String>(); private String yearMonthDay = ""; /**银行账户**/ private Account account; /** * 构造子函数 */ public Producer(Account a){ account = a; } /** * 是否发工资时间(以每月的1号12点为准发工资) * @return */ public boolean isPayOffTime(){ Calendar calendar = Calendar.getInstance(); calendar.setTime(DateConstant.getNowDate()); //先判断是否本月已经发过工资 yearMonth = calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH); if(recordPaySet.contains(yearMonth)){ return false; } //判断是否发工资时间 if(calendar.get(Calendar.DAY_OF_MONTH) == 1 && calendar.get(Calendar.HOUR_OF_DAY) == 12){ logger.info("-----------发工资时间: " + DateConstant.getNowDateForString()); return true; } return false; } /** * 是否利息结算时间(以每天的18点结算) * @return */ public boolean isInterestCountTime(){ Calendar calendar = Calendar.getInstance(); calendar.setTime(DateConstant.getNowDate()); //先判断是否今天已经结算过利息 yearMonthDay = calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH) + calendar.get(Calendar.DAY_OF_MONTH); if(recordInterestSet.contains(yearMonthDay)){ return false; } //logger.info("--->"+calendar.get(Calendar.HOUR_OF_DAY)); //判断是否利息结算时间 if(calendar.get(Calendar.HOUR_OF_DAY) == 18){ //logger.info("利息结算时间: " + DateConstant.getNowDateForString()); return true; } return false; } @Override public void run() { while(!DateConstant.isEnd()){ //如果还没有结束 if(isPayOffTime()){ //如果到了发工资时间 if(account.addMoney(18000)){ recordPaySet.add(yearMonth); } } if(isInterestCountTime()){ //如果到了利息结算时间 if(account.addMoney((float)(account.getMoney()*0.0001))){ recordInterestSet.add(yearMonthDay); } } DateConstant.timeRun(); logger.error("当前时间:" + DateConstant.getNowDateForString()); } logger.info("账户共有:" + account.getMoney() + "元"); } }
package pc.d3; import java.util.Calendar; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; /** * 消费者---交房租、生活费等开销每个月5000元 * @author zhoufy */ public class Consumer implements Runnable{ Logger logger = Logger.getLogger(Consumer.class); /**交房租记录**/ private Set<String> recordChummageSet = new HashSet<String>(); private String yearMonth = ""; /**银行账户**/ private Account account; /**房租N月一交**/ private int splitMonth = 3; /**上一次交房租月份**/ private int lastPayMonth = 0; /** * 构造子函数 */ public Consumer(Account a){ account = a; } /** * 是否消费时间(以每月的1号12点为交房租) * @return */ public boolean isPayOffTime(){ Calendar calendar = Calendar.getInstance(); calendar.setTime(DateConstant.getNowDate()); if(lastPayMonth==0){ lastPayMonth = calendar.get(Calendar.MONTH) - splitMonth; } //先判断是否已经交过房租 yearMonth = calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH); if(recordChummageSet.contains(yearMonth)){ return false; } //判断是否交房租时间 if(calendar.get(Calendar.MONTH)==(lastPayMonth+splitMonth) && calendar.get(Calendar.DAY_OF_MONTH) == 1 && calendar.get(Calendar.HOUR_OF_DAY) == 13){ logger.info("交房租时间: " + DateConstant.getNowDateForString()); lastPayMonth = calendar.get(Calendar.MONTH); return true; } return false; } @Override public void run() { while(!DateConstant.isEnd()){ //如果还没有结束 if(isPayOffTime()){ //如果到了交房租时间 if(account.subMoney(5000*splitMonth)){ //注意:这里是交房租金额=月房租数*一次性交的月数 recordChummageSet.add(yearMonth); } } } } }
package pc.d3; public class Main { public static void main(String[] args) { /**创建银行账户**/ Account account = new Account(); /**生产者**/ new Thread(new Producer(account)).start(); /**消费者**/ new Thread(new Consumer(account)).start(); } }
运行结果:
房租一个月一交,最后账户金额为:78841.414元
房租二个月一交,最后账户金额为:78795.43元
房租三个月一交,最后账户金额为:78747.89元
哎,看来还是一月一交省钱,可天下又有几个房东好心让租房者一个月一交房租呢!
我有一个梦想,愿有一天,中华儿女不再因租房而奔波劳碌!
说明:其中运行结果不是一次运行出来的,是分三次运行出来的,其中交房租方式是通过类Consumer.java中的splitMonth属性的值控制的。
推荐阅读
-
多线程编程之存钱与取钱 博客分类: 线程 java多线程存钱取钱thread
-
多线程编程之理财 博客分类: 线程 java多线程理财生产者消费者
-
Java多线程总结之线程安全队列Queue 博客分类: 多线程QueueBlockingQueueConcurrentLinkedQueue 多线程QueueBlockingQueueConcurrentLinkedQueue
-
多线程编程中条件变量和虚假唤醒(spurious wakeup)的讨论 博客分类: JAVA技术 多线程 同步 互斥 条件等待 信号量
-
多线程编程中条件变量和虚假唤醒(spurious wakeup)的讨论 博客分类: JAVA技术 多线程 同步 互斥 条件等待 信号量
-
线程同步模型, 生产者/消费者, 读写同步,线程池,concurrent map. 博客分类: Design 多线程thread数据结构log4j编程
-
Java并发编程:AtomicInteger&CAS 博客分类: Java多线程 Java并发编程AtomicIntegerCAS
-
Java并发编程:阻塞队列 博客分类: Java多线程 java阻塞队列
-
Java并发编程:阻塞队列 博客分类: Java多线程 java阻塞队列
-
Java并发编程:Callable、Future和FutureTask 博客分类: Java多线程 CallableFutureFutureTask