黑马程序员——关于多线程的总结


---------------------- 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)来锁定该线程










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值