---------------------- android培训、java培训、期待与您交流! ----------------------
1.关于Thread、Runnable和Callable的比较
Thread是通过集成来实现,继承了Thread类以后无法继承其他类,有一定的局限性
Callable与Runnable实现差不多,只是前者有返回值幕后者没有。
但是Callable与Runnable要访问当前线程必须使用Thread.currentThread()方法。
2.关于线程的生命周期:新建->就绪->运行->阻塞->死亡。
注意,当使用start()以后,是进入等待状态,将等待CUP执行,不是马上就开始执行。
控制线程的方法:join() 加入进来,直到加入进来的线程运行完毕才让出CPU
join(long times) 加入的进程执行最多times毫秒
setDaemon Thread (true) 设置成后台线程,其他线程结束以后,它不管执行结束与否大陆结束
sleep(long time) 该线程被停止times毫秒
yield()线程退回到等待执行的状态
线程安全:
一个有趣的实例
public class Account
{
// 封装账户编号、账户余额两个Field
private String accountNo;
private double balance;
public Account(){}
// 构造器
public Account(String accountNo , double balance)
{
this.accountNo = accountNo;
this.balance = balance;
}
// 此处省略了accountNo和balance两个Field的setter和getter方法
// accountNo的setter和getter方法
public void setAccountNo(String accountNo)
{
this.accountNo = accountNo;
}
public String getAccountNo()
{
return this.accountNo;
}
// balance的setter和getter方法
public void setBalance(double balance)
{
this.balance = balance;
}
public double getBalance()
{
return this.balance;
}
// 下面两个方法根据accountNo来重写hashCode()和equals()方法
public int hashCode()
{
return accountNo.hashCode();
}
public boolean equals(Object obj)
{
if(this == obj)
return true;
if (obj !=null
&& obj.getClass() == Account.class)
{
Account target = (Account)obj;
return target.getAccountNo().equals(accountNo);
}
return false;
}
}
public class DrawThread extends Thread
{
// 模拟用户账户
private Account account;
// 当前取钱线程所希望取的钱数
private double drawAmount;
public DrawThread(String name , Account account
, double drawAmount)
{
super(name);
this.account = account;
this.drawAmount = drawAmount;
}
// 当多条线程修改同一个共享数据时,将涉及数据安全问题。
public void run()
{
// 账户余额大于取钱数目
if (account.getBalance() >= drawAmount)
{
// 吐出钞票
System.out.println(getName()
+ "取钱成功!吐出钞票:" + drawAmount);
try
{
Thread.sleep(1);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
// 修改余额
account.setBalance(account.getBalance() - drawAmount);
System.out.println("\t余额为: " + account.getBalance());
}
else
{
System.out.println(getName() + "取钱失败!余额不足!");
}
}
}
public class DrawTest
{
public static void main(String[] args)
{
// 创建一个账户
Account acct = new Account("1234567" , 1000);
// 模拟两个线程对同一个账户取钱
new DrawThread("甲" , acct , 800).start();
new DrawThread("乙" , acct , 800).start();
}
}
运行上面代码可能会出现一个有趣的现象:甲乙都取钱成功,余额为负。出现这样的情况的原因是甲线程取钱成功以后就被乙给夺取了控制
所以要解决这个问题,应该保证每一个线程都执行完以后再执行下一线程。可以再run方法中加入synchronized(account)来锁定该线程