package AccountThread02;
public class Account {
private String username;
private double balance;
Object obj = new Object();//实例变量
public Account() {
}
public Account(String username, double balance) {
this.username = username;
this.balance = balance;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void withdraw(double money) {
/**
*
* 1、该怎样让线程等待呢?
* synchronized方法,让进程等待
* 用法:synchronized(共享){
* //线程同步代码块
* }
* ()里的数据时相当关键的,这个数据必须是多线程共享的数据(这里是账户对象)
* 才能达到多线程排队
* ()中写什么?
* 假设有1,2,3,4,5,五个线程
* 如果希望1,2,3,排队就些1,2,3,共享的对象,而这个对象虽4和5是不共享的(比如,4和5的对象是另一个账户)
*
* 2、java中,每个对象都有“一把锁”,其实这把锁就是标记
* 3、以下代码的执行原理:
* 1、假设1和2线程并发,开始执行以下代码的时候,肯定有一个先一个后
*
* 2、假设1先执行,遇到了synchronized,这个时候自动找”后面共享对象“的对象锁
* 找到之后,占有它,然后执行同步代码块中的程序,执行过程中一直占有着这把锁,直到
* 同步代码块结束,这把锁才会释放
*
* 3、假设1占有了这把锁,2也遇到了synchronized关键字,也会去找有后面共享对象的这个锁
* 但是发现这把锁已经被1占有,2只能在同步代码块外面等待1的结束,直到1把同步代码块执行结束
* 1归还这个锁,进入同步代码块执行程序
* 这样就达到了线程排队执行
* 注意:这个共享对象一定要选好,一定是你需要排队执行这些线程对象所共享的
*/
synchronized (this) {
// synchronized (obj) { obj是可以的,是共享的,具体可以看图
// synchronized ("abc"){ abc是可以的,但是所有的线程都会排队,因为所有的线程都共享字符串
//字符串在常量池中,为所有线程的共享的
double before = this.getBalance();
double after = before - money;
this.setBalance(after);
System.out.println(Thread.currentThread().getName() + money + "取款成功," + "余额:" + this.getBalance());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package AccountThread02;
public class AccountThread extends Thread{
private Account account;
public AccountThread(Account account) {
this.account = account;
}
@Override
public void run() {
synchronized (account){
account.withdraw(5000);
}
account.withdraw(5000);
}
}
package AccountThread02;
public class Test {
public static void main(String[] args) {
Account aa = new Account("adff",10000);
Thread bb = new AccountThread(aa);
Thread cc = new AccountThread(aa);
bb.setName("线程一");
cc.setName("线程二");
bb.start();
cc.start();
}
}
package AccountThread03;
public class Account {
private String username;
private double balance;
Object obj = new Object();
public Account() {
}
public Account(String username, double balance) {
this.username = username;
this.balance = balance;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public synchronized void withdraw(double money) {
double before = this.getBalance();
double after = before - money;
this.setBalance(after);
System.out.println(Thread.currentThread().getName() + money + "取款成功," + "余额:" + this.getBalance());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package AccountThread03;
public class AccountThread extends Thread{
private Account account;
public AccountThread(Account account) {
this.account = account;
}
@Override
public void run() {
synchronized (account){
account.withdraw(5000);
}
account.withdraw(5000);
}
}
package AccountThread03;
public class Test {
public static void main(String[] args) {
Account aa = new Account("adf",10000);
Thread bb = new AccountThread(aa);
Thread cc = new AccountThread(aa);
bb.setName("线程一");
cc.setName("线程二");
bb.start();
cc.start();
}
}