近期想回顾一些知识:
一、Java 多线程
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
二、区别
三、模拟银行ATM存取钱
1、 用户类user,存储用户信息
import java.util.Date;
public class User {
private String u_name;//用户名
private String u_login_name;//登录名 卡的id
private String u_login_pwd;//登录密码
private String u_wallet;//钱包
private Date draw_money_time;//取钱时间
private Date save_money_time;//存钱时间
public User(){}
public User(String u_name, String u_login_name, String u_login_pwd, String u_wallet) {
this.u_name = u_name;
this.u_login_name = u_login_name;
this.u_login_pwd = u_login_pwd;
this.u_wallet = u_wallet;
}
public User(String u_name, String u_login_name, String u_login_pwd, String u_wallet, Date draw_money_time, Date save_money_time) {
this.u_name = u_name;
this.u_login_name = u_login_name;
this.u_login_pwd = u_login_pwd;
this.u_wallet = u_wallet;
this.draw_money_time = draw_money_time;
this.save_money_time = save_money_time;
}
public String getU_name() {
return u_name;
}
public void setU_name(String u_name) {
this.u_name = u_name;
}
public String getU_login_name() {
return u_login_name;
}
public void setU_login_name(String u_login_name) {
this.u_login_name = u_login_name;
}
public String getU_login_pwd() {
return u_login_pwd;
}
public void setU_login_pwd(String u_login_pwd) {
this.u_login_pwd = u_login_pwd;
}
public String getU_wallet() {
return u_wallet;
}
public void setU_wallet(String u_wallet) {
this.u_wallet = u_wallet;
}
public Date getDraw_money_time() {
return draw_money_time;
}
public void setDraw_money_time(Date draw_money_time) {
this.draw_money_time = draw_money_time;
}
public Date getSave_money_time() {
return save_money_time;
}
public void setSave_money_time(Date save_money_time) {
this.save_money_time = save_money_time;
}
}
2、 取款类ATM:有取款机的相应功能
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 取款机
* 2018/6/8
* wtj
*/
public class ATM {
private List userList=new ArrayList<>();
public ATM(){}
public ATM(List userList) {
this.userList = userList;
}
public List getUserList() {
return userList;
}
public void setUserList(List userList) {
this.userList = userList;
}
//存钱
public Boolean saveMoney(String card,String pwd,String moneyNum){
User u=getUserByCard(card);
synchronized (ATM.class) {
if (u.getU_login_name().equals(card) && u.getU_login_pwd().equals(pwd)) {
BigDecimal oldData=new BigDecimal(u.getU_wallet());
BigDecimal money=new BigDecimal(moneyNum);
u.setU_wallet(oldData.add(money).toString());
u.setSave_money_time(new Date());
System.out.println(Thread.currentThread().getName()+"存钱---->"+u.getU_name()+"在"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(u.getSave_money_time())+"存["+moneyNum+"]钱,余额:"+u.getU_wallet());
return true;
}
}
System.out.println(getUserByCard(card).getU_name()+"存钱失败");
return false;
}
//取钱
public Boolean getMoney(String card,String pwd,String moneyNum){
User u=getUserByCard(card);
synchronized (ATM.class) {
if (u!=null && u.getU_login_name().equals(card) && u.getU_login_pwd().equals(pwd)) {
BigDecimal oldData=new BigDecimal(u.getU_wallet());
BigDecimal money=new BigDecimal(moneyNum);
if(oldData.compareTo(money)>=0){
u.setU_wallet(oldData.subtract(money).toString());
u.setDraw_money_time(new Date());
System.out.println(Thread.currentThread().getName()+"取钱---->"+u.getU_name()+"在"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(u.getDraw_money_time())+"取["+moneyNum+"]钱,余额:"+u.getU_wallet());
return true;
}else {
System.out.println(getUserByCard(card).getU_name()+"余额不足");
return false;
}
}
}
System.out.println(card+"取钱失败");
return false;
}
//查询余额
public String balanceEnquiry(String card,String pwd){
for(User u :this.userList){
if(u.getU_login_name().equals(card)&& u.getU_login_pwd().equals(pwd)){
System.out.println(Thread.currentThread().getName()+":"+u.getU_name()+"余额:"+u.getU_wallet());
return u.getU_wallet();
}
}
System.out.println(Thread.currentThread().getName()+":"+card+"操作失败");
return null;
}
//获取当前用户
public synchronized User getUserByCard(String card){
for(User u :this.userList){
if(u.getU_login_name().equals(card)){
return u;
}
}
return null;
}
public void delayTime(Integer nim){
try {
Thread.sleep(nim);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、测试类:模拟多次存取钱
import java.util.ArrayList;
import java.util.List;
public class TreadTextMain {
public static void main(String[] args) throws Exception {
User u = new User("赵云", "132466", "123", "100");
User uu = new User("鲁班", "4600882", "123", "0");
List list = new ArrayList<>();
list.add(u);
list.add(uu);
ATM atm = new ATM(list);//初始化数据 模拟
Thread t = new Thread() {
public void run() {
// ATM atm = new ATM(list);
for (int i = 0; i < 20; i++) {
atm.saveMoney("132466", "123", "12");
atm.delayTime(250);
atm.getMoney("4600882", "123", "14");
atm.delayTime(250);
}
// atm.balanceEnquiry("4600882", "123");
// atm.balanceEnquiry("132466", "123");
}
};
Thread tt = new Thread() {
public void run() {
// ATM atm = new ATM(list);
for (int i = 0; i < 20; i++) {
atm.getMoney("132466", "123", "2");
atm.delayTime(250);
atm.saveMoney("4600882", "123", "12");
atm.delayTime(250);
}
// atm.balanceEnquiry("4600882", "123");
// atm.balanceEnquiry("132466", "123");
}
};
t.start();
tt.start();
// atm.balanceEnquiry("4600882", "123");
// atm.balanceEnquiry("132466", "123");
}
}
四、总结
(1)synchronized的使用:synchronized可以使用在方法上,也可以使用在代码块上;如果我们需要用到不同的线程(多线程),注意synchronized(xxx.class){}、synchronized(this){} 后的效果;
看这篇文章https://www.cnblogs.com/huansky/p/8869888.html
(2)线程安全,简单的理解:多线程执行代码的结果,要跟单流程执行代码的结果一样;