线程的三种不安全问题
问题一:买票问题
package Unsafe;
public class Unsafebuyt {
public static void main(String[] args) {
Unsafe unsafe=new Unsafe();
new Thread(unsafe,"小明").start();//开启线程
new Thread(unsafe,"小红").start();
new Thread(unsafe,"小兰").start();
}
}
class Unsafe implements Runnable{
boolean flag=true;
//票
private int ticket=10;
@Override
//买票
public void run() {
while (flag){
//当标志位是true的时候执行,当变为false时停止方法
buy();}
}
//怎么买
private void buy(){
if(ticket<=0){
//如果票没了,标志位变为false
flag=false;
return;//跳出方法
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---->"+ticket--);
}
}
解决办法
问题二:取钱问题
package Unsafe;
/**
* 账户
* 银行
*/
public class Unbank {
public static void main(String[] args) {
Account account = new Account(100,"你的钱");//规定账户名字和卡内余额
Bank girlfriend = new Bank(account,100,"girlfriend");//模拟一个线程
Bank bank = new Bank(account,50,"你");//模拟一个线程
girlfriend.start();//开启线程
bank.start();
}
}
//银行卡账户 有钱和名字
class Account {
int money;
String name;
public Account( int money, String name) {
//用构造器获取这个名字
this.money=money;
this.name = name;
}
}
//银行 有账户、账户余额;
class Bank extends Thread{
Account account;//账户
int nowmoney;//手里的钱
int movemoney;//要取走的钱
public Bank(Account account, int movemoney, String name) {
super(name);//super写在首行 调用父类的名字==就是线程的名字(自己规定)
this.account= account;//获取账户
this.movemoney = movemoney;//账户要取走的钱
}
@Override
public void run() {
//开始取钱过程 银行要做的事
if(account.money-movemoney<=0){
//账户余额<要取走的钱
System.out.println(Thread.currentThread().getName()+"卡内余额不足");
return;//跳出方法
}
try {
//模拟延时,因为要最少两个人取钱
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(account.name+"卡内余额"+account.money);
account.money=account.money-movemoney;//更新卡内余额
nowmoney=nowmoney+movemoney;//更新手里的钱
System.out.println(getName()+"取走的钱"+nowmoney);
System.out.println(account.name+"卡内余额"+account.money);
}
}
解决办法
问题三:线程内不安全集合问题
package Unsafe;
import java.util.ArrayList;
import java.util.List;
public class UnsafeList {
public static void main(String[] args) {
List<String> list =new ArrayList<String>();//新建数组集合
for (int i = 0; i <= 10000; i++) {
//循环开启10000个线程
new Thread(()->//lambda表达式
list.add(Thread.currentThread().getName())//把线程加到list里
).start();//开启线程
}
//模拟延时
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
//输出集合大小
System.out.println(list.size());
}
}
解决办法
或者可用JUC并发编程
package Unsafe;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestJuc {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<>();
for (int i = 0; i < 10000; i++) {
//循环开启10000个线程
new Thread(()->{
//lambda表达式
list.add(Thread.currentThread().getName());//把线程加到list里
}).start();//开启线程
}
//模拟延时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
//输出集合大小
System.out.println(list.size());
}
}