实验一 多线程同步处理 java

更新时间:2023-12-13 22:49:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验一:多线程同步处理

实现内容:编写一多线程程序,实现对某一银行帐户的存取款操作。

要求:多个用户均可操作该帐户,存款随意存,取款要求帐户的余额足够才能取(不能透支)。每一项存取款操作均要互斥进行。

参考资料:http://lavasoft.blog.51cto.com/62575/27069

前半部分代码:

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

* Java线程:条件变量 *

* @author leizhimin 2009-11-5 10:57:29 */

public class Test {

public static void main(String[] args) { //创建并发访问的账户

MyCount myCount = new MyCount(\, 10000); //创建一个线程池

ExecutorService pool = Executors.newFixedThreadPool(2); Thread t1 = new SaveThread(\张三\, myCount, 2000); Thread t2 = new SaveThread(\李四\, myCount, 3600); Thread t3 = new DrawThread(\王五\, myCount, 14100); Thread t4 = new SaveThread(\老张\, myCount, 600); Thread t5 = new DrawThread(\老牛\, myCount, 1300); Thread t6 = new DrawThread(\胖子\, myCount, 800); //执行各个线程

pool.execute(t1); pool.execute(t2); pool.execute(t3); pool.execute(t4); pool.execute(t5); pool.execute(t6); //关闭线程池

pool.shutdown(); } }

/**

* 存款线程类 */

class SaveThread extends Thread {

private String name; //操作人 private MyCount myCount; //账户

private int x; //存款金额

SaveThread(String name, MyCount myCount, int x) { this.name = name;

this.myCount = myCount; this.x = x; }

public void run() {

System.out.println(name+\存款操作\+x); myCount.saving(x, name); } }

/**

* 取款线程类 */

class DrawThread extends Thread {

private String name; //操作人 private MyCount myCount; //账户

private int x; //存款金额

DrawThread(String name, MyCount myCount, int x) { this.name = name;

this.myCount = myCount; this.x = x; }

public void run() { System.out.println(name+\取款操作\+x); myCount.drawing(x, name); } }

后半部分代码:

MyCount的三种实现方法: 方法一:

/** 条件变量的实现方式 * 普通银行账户,不可透支 */

class MyCount {

private String oid; //账号

private int cash; //账户余额

private Lock lock = new ReentrantLock(); //账户锁 。一次只能有一个线程获得锁。

private Condition _draw = lock.newCondition(); //取款条件

MyCount(String oid, int cash) { this.oid = oid; this.cash = cash; }

/** * 存款 *

* @param x 操作金额 * @param name 操作人 */

public void saving(int x, String name) {

lock.lock(); //获取锁 if (x > 0) {

cash += x; //存款

System.out.println(name + \存款\ + x + \,当前余额为\ + cash);

}

_draw.signalAll(); //唤醒所有等待线程。

lock.unlock(); //释放锁 }

/** * 取款 *

* @param x 操作金额 * @param name 操作人 */

public void drawing(int x, String name) {

lock.lock(); //获取锁 try {

while (cash - x < 0) {

_draw.await(); //阻塞取款操作 }

cash -= x; //取款

System.out.println(name + \取款\ + x + \,当前余额为\ + cash);

_draw.signalAll(); //唤醒所有等待线程。 } catch (InterruptedException e) { e.printStackTrace(); } finally {

lock.unlock(); //释放锁 } } }

方法二:

/** 利用 同步方法 来实现 * 普通银行账户,不可透支 */

class MyCount {

private String oid; //账号

private int cash; //账户余额

MyCount(String oid, int cash) { this.oid = oid; this.cash = cash; }

/** * 存款 *

* @param x 操作金额 * @param name 操作人 */

/* synchronized

* Java中每个对象都有一个内置锁

当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例

(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。

当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

释放锁是指持锁线程退出了synchronized同步方法或代码块。

关于锁和同步,有一下几个要点:

1)、只能同步方法,而不能同步变量和类; 2)、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步? 3)、不必同步类中所有的方法,类可以同时拥有同步和非同步方法。

4)、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。

5)、如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。

* */

public synchronized void saving(int x, String name) { if (x > 0) {

cash += x; //存款

System.out.println(name + \存款\ + x + \,当前余额为\ + cash);

}

notifyAll(); //唤醒所有等待线程。 }

/** * 取款 *

* @param x 操作金额 * @param name 操作人 */

public synchronized void drawing(int x, String name) { while (cash - x < 0) { try {

wait();

} catch (InterruptedException e1) { e1.printStackTrace(); } }

cash -= x; //取款

System.out.println(name + \取款\ + x + \,当前余额为\ + cash);

notifyAll(); //唤醒所有存款操作 } }

方法三:

/** 利用同步代码块来实现 * 普通银行账户,不可透支 */

class MyCount {

private String oid; //账号

private int cash; //账户余额

MyCount(String oid, int cash) { this.oid = oid; this.cash = cash; }

/** * 存款 *

* @param x 操作金额 * @param name 操作人 */

public void saving(int x, String name) { if (x > 0) {

synchronized (this) {

cash += x; //存款

System.out.println(name + \存款\ + x + \,当前余额为\ + cash);

notifyAll(); //唤醒所有等待线程。 } } }

/** * 取款 *

* @param x 操作金额 * @param name 操作人 */

public synchronized void drawing(int x, String name) { synchronized (this) {

while (cash - x < 0) { try {

wait();

} catch (InterruptedException e1) { e1.printStackTrace(); } }

cash -= x; //取款

System.out.println(name + \取款\ + x + \,当前余额为\ + cash);

}

notifyAll(); //唤醒所有存款操作 } }

本文来源:https://www.bwwdw.com/article/cz45.html

Top