Java线程同步实例分析

网友投稿 198 2023-07-31


Java线程同步实例分析

本文实例讲述了java线程同步的用法。分享给大家供大家参考。具体分析如下:

多线程的使用为我们的程序提供了众多的方便,同时它也给我们带来了以往没有考虑过的麻烦。当我们使用多线程处理共享资源时意外将会发生:比如我们一起外出就餐,每个人都是一个线程,餐桌上的食物则是共享资源,当我看到红烧鸡腿上桌后立即拿起筷子直奔目标,眼看着就得手的时候,突然~~~鸡腿消失了,一个距离盘子更近的线程正在得意地啃着。

为了避免上述问题的发生,Java为我们提供了“synchronized(同步化)修饰符”来避免资源冲突,你可以将资源类中某个函数或变量声明为synchronized(同步化),每个继承自Object的类都含有一个机锁(Lock),它是余生俱来的,不需要编写任何代码来启用它。当我们调用任何synchronized(同步化)函数时,该对象将被锁定,对象中所有 synchronized(同步化)函数便无法被调用,直到第一个函数执行完毕并解除机锁。

import java.awt.BorderLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.jscrollPaneGntTKzMi;

import javax.swing.JTextArea;

import javax.swing.JTextField;

/**

* 线程同步

* 我们模拟一个银行存储过程来证明线程同步的必要性以及在Java中进行线程同步的方法

* 重点:synchronized 修饰符

*/

public class TestMain5 extends JFrame {

private MyAccounts myAccounts = null; // 我的帐号

private JTextField text = null; // 银行存款数额显示

private JTextArea textArea = null; // 交易过程显示

private JButton button = null; // 开始模拟交易的按钮

/**

* 构造一个银行存取款界面

*/

public TestMain5(){

super("线程同步测试");

myAccounts = new MyAccounts();

text = new JTextField(Integer.toString(myAccounts.inquire()), 10); // 我们在银行中的初始存款为100

textArea = new JTextArea();

textArea.setText("交易日志:");

JScrollPane sp = new JScrollPane(textArea);

button = new JButton("开始交易");

button.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e) {

new Bank("钟楼支行", myAccounts, Bank.DEAL_SAVING, 800);

new Bank("高新支行", myAccounts, Bank.DEAL_SAVING, 1300);

new Bank("小寨支行", myAccounts, Bank.DEAL_FETCH, 200);

new Bank("雁塔支行", myAccounts, Bank.DEAL_FETCH, 400);

new Bank("兴庆支行", myAccounts, Bank.DEAL_SAVING, 100);

new Bank("土门支行", myAccounts, Bank.DEAL_FETCH, 700);

}

});

JPanel pane = new JPanel();

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个交易大厅,这些大厅可以同时处理多笔业务,这正好符合多线程的特点

*/

class Bank extends Thread{

/**

* 静态字段:用于表示储存

*/

public static final int DEAL_SAVING = 0;

/**

* 静态字段:用于表示提取

*/

public static final int DEAL_FETCH = 1;

private int buy = Bank.DEAL_FETCH; // 默认使取款

private int count = 0;

private MyAccounts myAccounts = null; // 我的帐号

/**

* 构造这个银行交易大厅

* @param name 这个交易大厅的名称

* @param myAccounts 我的银行帐号

* @param buy 行为,参考字段:DEAL_SAVING或DEAL_FETCH

* @param count 钱的数量

*/

public Bank(String name, MyAccounts myAccounts, int buy, int count){

super(name);

this.myAccounts = myAccounts;

this.buy = buy;

this.count = count;

this.start();

}

public void run(){

int $count = 0;

if(buy == Bank.DEAL_SAVING){ // 如果是存款业务

$count = myAccounts.saving(count);

}else if(buy == Bank.DEAL_FETCH){ // 如果是取款业务

$count = myAccounts.fetch(count);

}

text.setText(Integer.toString($count));

textArea.append("\n" + this.getName() + " " + (buy == Bank.DEAL_SAVING ? "存款": "取款") + " 金额:" + count + " 结余:" + $count);

}

}

/**

* 我的帐号

* 进行同步测试

*/

class MyAccounts{

private Integer count = 1100;

public MyAccounts(){

}

/**

* 查询我的帐号

*/

public int inquire(){

synchronized (count){

return count;

}

}

/**

* 存款业务

* @param c 存款的数量

* @return 业务办理完成后的数量

*/

public int saving(int c){

synchronized (count){

//return count += c; // 为了能更好的观察,我们将这个简洁的语句注释掉

int $count = inquire(); // 先查询帐户中的存款

$count += c;

try {

Thread.sleep(1000); // 为了更好的观察,使业务在此停顿1秒钟

} catch (InterruptedException ex) {

ex.printStackTrace();

}

count = $count; // 最后将总数储存起来

return inquire(); // 返回最新的存款数

}

}

/**

* 取款业务

* @param c 取款的数量

* @return 业务办理完成后的数量

*/

public int fetch(int c){

synchronized (count){

//return count -= c; // 为了能更好的观察,我们将这个简洁的语句注释掉

int $counGntTKzMit = inquire(); // 先查询帐户中的存款

$count -= c;

try {

Thread.sleep(1000); // 为了更好的观察,使业务在此停顿1秒钟

} catch (InterruptedException ex) {

ex.printStackTrace();

}

count = $count; // 最后将总数储存起来

return inquire(); // 返回最新的存款数

}

}

}

public static void main(String [] args){

new TestMain5();

}

}

希望本文所述对大家的java程序设计有所帮助。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java线程之守护线程(Daemon)用法实例
下一篇:Java模拟QQ桌面截图功能实现方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~