案例介绍:
设计一个程序,使用两个线程模拟在两个地点同时从一个账号中取钱,假如卡中一共有1000元,每个线程取800元,要求演示结果一个线程取款成功,剩余200元,另一个线程取款失败,余额不足;
要求:
1:使用线程池创建线程
2:解决线程安全问题
思路提示:
1:线程池可以利用Executors工厂类的静态方法,创建线程池对象;
2:解决线程安全问题可以使用synchronized方法控制取钱的操作;
3:在取款前,先判断余额是否足够,且保证余额判断和取钱行为的原子性;
代码:
编写任务类
public class MyTask implements Runnable {
//用户姓名
private String userName;
//取款金额
private double money;
//总金额
private static double total = 1000;
public MyTask(String userName, double money) {
this.userName = userName;
this.money = money;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(userName+"正在准备使用"+name+"取款:"+money+"元");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (MyTask.class){
if(total-money>0){
System.out.println(userName+"使用"+name+"取款:"+money+"元成功,余额:"+(total-money));
total-=money;
}else {
System.out.println(userName+"使用"+name+"取款:"+money+"元失败,余额:"+total);
}
}
}
}
编写测试类
public class MyTest {
public static void main(String[] args) {
//1:创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2, new ThreadFactory() {
int id = 1;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "ATM" + id++);
}
});
//2:创建两个任务并提交
for (int i = 1; i <=2 ; i++) {
MyTask myTask = new MyTask("客户" + i, 800);
pool.submit(myTask);
}
//3:关闭线程池
pool.shutdown();
}
}