Java线程同步实例分析
本文实例讲述了Java线程同步的用法。分享给大家供大家参考。具体分析如下:
多线程的使用为我们的程序提供了众多的方便,同时它也给我们带来了以往没有考虑过的麻烦。当我们使用多线程处理共享资源时意外将会发生:比如我们一起外出就餐,每个人都是一个线程,餐桌上的食物则是共享资源,当我看到红烧鸡腿上桌后立即拿起筷子直奔目标,眼看着就得手的时候,突然~~~鸡腿消失了,一个距离盘子更近的线程正在得意地啃着。
为了避免上述问题的发生,Java为我们提供了“synchronized(同步化)修饰符”来避免资源冲突,你可以将资源类中某个函数或变量声明为synchronized(同步化),每个继承自Object的类都含有一个机锁(Lock),它是余生俱来的,不需要编写任何代码来启用它。当我们调用任何synchronized(同步化)函数时,该对象将被锁定,对象中所有synchronized(同步化)函数便无法被调用,直到第一个函数执行完毕并解除机锁。
importjava.awt.BorderLayout; importjava.awt.event.ActionEvent; importjava.awt.event.ActionListener; importjavax.swing.JButton; importjavax.swing.JFrame; importjavax.swing.JPanel; importjavax.swing.JScrollPane; importjavax.swing.JTextArea; importjavax.swing.JTextField; /** *线程同步 *我们模拟一个银行存储过程来证明线程同步的必要性以及在Java中进行线程同步的方法 *重点:synchronized修饰符 */ publicclassTestMain5extendsJFrame{ privateMyAccountsmyAccounts=null;//我的帐号 privateJTextFieldtext=null;//银行存款数额显示 privateJTextAreatextArea=null;//交易过程显示 privateJButtonbutton=null;//开始模拟交易的按钮 /** *构造一个银行存取款界面 */ publicTestMain5(){ super("线程同步测试"); myAccounts=newMyAccounts(); text=newJTextField(Integer.toString(myAccounts.inquire()),10);//我们在银行中的初始存款为100 textArea=newJTextArea(); textArea.setText("交易日志:"); JScrollPanesp=newJScrollPane(textArea); button=newJButton("开始交易"); button.addActionListener(newActionListener(){ publicvoidactionPerformed(ActionEvente){ newBank("钟楼支行",myAccounts,Bank.DEAL_SAVING,800); newBank("高新支行",myAccounts,Bank.DEAL_SAVING,1300); newBank("小寨支行",myAccounts,Bank.DEAL_FETCH,200); newBank("雁塔支行",myAccounts,Bank.DEAL_FETCH,400); newBank("兴庆支行",myAccounts,Bank.DEAL_SAVING,100); newBank("土门支行",myAccounts,Bank.DEAL_FETCH,700); } }); JPanelpane=newJPanel(); pane.add(text); pane.add(button); this.getContentPane().add(pane,BorderLayout.NORTH); this.getContentPane().add(sp); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setSize(300,200); this.setLocationRelativeTo(null); this.setVisible(true); } /** *银行交易大厅类 *一般银行都会有N个交易大厅,这些大厅可以同时处理多笔业务,这正好符合多线程的特点 */ classBankextendsThread{ /** *静态字段:用于表示储存 */ publicstaticfinalintDEAL_SAVING=0; /** *静态字段:用于表示提取 */ publicstaticfinalintDEAL_FETCH=1; privateintbuy=Bank.DEAL_FETCH;//默认使取款 privateintcount=0; privateMyAccountsmyAccounts=null;//我的帐号 /** *构造这个银行交易大厅 *@paramname这个交易大厅的名称 *@parammyAccounts我的银行帐号 *@parambuy行为,参考字段:DEAL_SAVING或DEAL_FETCH *@paramcount钱的数量 */ publicBank(Stringname,MyAccountsmyAccounts,intbuy,intcount){ super(name); this.myAccounts=myAccounts; this.buy=buy; this.count=count; this.start(); } publicvoidrun(){ int$count=0; if(buy==Bank.DEAL_SAVING){//如果是存款业务 $count=myAccounts.saving(count); }elseif(buy==Bank.DEAL_FETCH){//如果是取款业务 $count=myAccounts.fetch(count); } text.setText(Integer.toString($count)); textArea.append("\n"+this.getName()+""+(buy==Bank.DEAL_SAVING?"存款":"取款")+"金额:"+count+"结余:"+$count); } } /** *我的帐号 *进行同步测试 */ classMyAccounts{ privateIntegercount=1100; publicMyAccounts(){ } /** *查询我的帐号 */ publicintinquire(){ synchronized(count){ returncount; } } /** *存款业务 *@paramc存款的数量 *@return业务办理完成后的数量 */ publicintsaving(intc){ synchronized(count){ //returncount+=c;//为了能更好的观察,我们将这个简洁的语句注释掉 int$count=inquire();//先查询帐户中的存款 $count+=c; try{ Thread.sleep(1000);//为了更好的观察,使业务在此停顿1秒钟 }catch(InterruptedExceptionex){ ex.printStackTrace(); } count=$count;//最后将总数储存起来 returninquire();//返回最新的存款数 } } /** *取款业务 *@paramc取款的数量 *@return业务办理完成后的数量 */ publicintfetch(intc){ synchronized(count){ //returncount-=c;//为了能更好的观察,我们将这个简洁的语句注释掉 int$count=inquire();//先查询帐户中的存款 $count-=c; try{ Thread.sleep(1000);//为了更好的观察,使业务在此停顿1秒钟 }catch(InterruptedExceptionex){ ex.printStackTrace(); } count=$count;//最后将总数储存起来 returninquire();//返回最新的存款数 } } } publicstaticvoidmain(String[]args){ newTestMain5(); } }
希望本文所述对大家的java程序设计有所帮助。