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程序设计有所帮助。
