Java设计模式之外观模式示例详解
290
2022-07-31
第一种方法:同步代码块:
作用:把出现线程安全的核心代码上锁
原理:每次只能一个线程进入,执行完毕后自行解锁,其他线程才能进来执行
锁对象要求:理论上,锁对象只要对于当前同时执行的线程是同一个对象即可
缺点:会干扰其他无关线程的执行
所以,这种只是理论上的,了解即可,现实中并不会这样用
public class 多线程_4线程同步 {
public static void main(String[] args) {
//定义线程类,创建一个共享的账户对象
account a=new account("abc",10000);
//创建两个取钱的线程对象
new drawthread(a,"小明").start();
new drawthread(a,"小红").start();
}
}
//取钱的线程类
class drawthread extends Thread{
//接收处理的账户对象
private account acc;
public drawthread(account acc,String name){
super(name);
this.acc=acc;
}
public void run(){
//取钱
acc.drawmoney(10000);
}
}
class account{
private String cartId;
private double money;//账户余额
public account() {
}
public account(String cartId, double money) {
this.cartId = cartId;
this.money = money;
}
public String getCartId() {
return cartId;
}
public void setCartId(String cartId) {
this.cartId = cartId;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public void drawmoney(double money) {
//先获取是谁来取钱,线程名即是人名
String name=Thread.currentThread().getName();
//同步代码块
//作用:把出现线程安全的核心代码上锁
//原理:每次只能一个线程进入,执行完毕后自行解锁,其他线程才能进来执行
//锁对象要求:理论上,锁对象只要对于当前同时执行的线程是同一个对象即可
//缺点:会干扰其他无关线程的执行
WvTMBJYif synchronized ("遇安") {//"锁名自取,无意义"
//判断账户是否够钱
if(this.money>=money){
//取钱
System.out.println(name+"来取钱成功,取了:"+money);
//更新金额
this.money-=money;
System.out.println(name+"取钱后剩余:"+this.money);
}else{
//余额不足
System.out.println(name+"来取钱,但余额不足!");
}
}
}
}
规范上:建议使用共享资源作为锁对象
对于实例化方法建议使用this作为锁对象
对于静态方法,建议使用字节码(类名.class)对象作为锁对象
//接上文代码
//实例化方法建议使用this作为锁对象
synchronized (this) {
//判断账户是否够钱
if(this.money>=money){
//取钱
System.out.println(name+"来取钱成功,取了:"+money);
//更新金额
this.money-=money;
System.out.println(name+"取钱后剩余:"+this.money);
}else{
//余额不足
System.out.println(name+"来取钱,但余额不足!");
}
}
//静态方法建议使用类名.class作为锁对象
//每次只有一个线程能锁这个类,而类也是唯一的
public static void run(){
synchronized(account.class){
}
}
第二种方法:同步方法
//同步方法
public synchronized void drawmoney(double money) {
//先获取是谁来取钱,线程名即是人名
String name=Thread.currentThread().getName();
//判断账户是否够钱
if(this.money>=money){
//取钱
System.out.println(name+"来取钱成功,取了:"+money);
//更新金额
this.money-=money;
System.out.println(name+"取钱后剩余:"+this.money);
}else{
WvTMBJYif//余额不足
System.out.println(name+"来取钱,但余额不足!");
}
}
那么同步代码块和同步方法哪个好一点呢?
答案是:同步代码块
因为同步代码块锁的范围更小一点,同步方法锁的范围更大一点
但其实在现实中同步方法用的更多一点,因为代码简洁好写一点,更方便
第三种方法:Lock锁
JDK5后出现,更加灵活方便
Lock是接口不能直接实例化,我们需要采用它的实现类ReentrantLock来构建Lock锁对象
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class 多线程_4线程同步Lock锁 {
public static void main(String[] args) {
//定义线程类,创建一个共享的账户对象
account a=new account("abc",10000);
//创建两个取钱的线程对象
new drawthread(a,"小明").start();
new drawthread(a,"小红").start();
}
}
//取钱的线程类
class drawthread2 extends Thread{
//接收处理的账户对象
private account acc;
public drawthread2(account acc,String name){
super(name);
this.acc=acc;
}
public void run(){
//取钱
acc.drawmoney(10000);
}
}
class account2{
private String cartId;
private double money;//账户余额
//final修饰后:锁对象是唯一的和不可替换的
//Lock是接口不能直接实例化,我们需要采用它的实现类ReentrantLock来构建Lock锁对象
private final Lock lock=new ReentrantLock();
public account2() {
}
public account2(String cartId, double money) {
this.cartId = cartId;
this.money = money;
}
public String getCartId() {
return cartId;
}
public void setCartId(String cartIdWvTMBJYif) {
this.cartId = cartId;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public void drawmoney(double money) {
//先获取是谁来取钱,线程名即是人名
String name=Thread.currentThread().getName();
lock.lock();//上锁
//判断账户是否够钱
try {
if(this.money>=money){
//取钱
System.out.println(name+"来取钱成功,取了:"+money);
//更新金额
this.money-=money;
System.out.println(name+"取钱后剩余:"+this.money);
}else{
//余额不足
System.out.println(name+"来取钱,但余额不足!");
}
//防止代码出现bug而不能解锁
} finally {
lock.unlock();//解锁
}
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~