[b]1.基础概念[/b]

[b]1.1线程:[/b]共存于同一个进程直接的工具,独立并发执行,有自己的堆栈,程序计数器和局部变量。但是共享内存,文件句柄和进程的状态。


[b]1.2为何使用线程:[/b]更快的响应,充分利用多处理系统,异步处理用于分解大型任务。


[b]1.3使用线程注意:[/b]不要过分使用,特别是在轮询等待的情况下,机器资源消耗比较严重;在多个线程方位共享变量时主要保持同步;


[b]1.4如何实现简单的Java多线程程序:[/b]extends Thread或者implements Runnable,但本质上都是需要实例化Thread,才能使用多线程。


[b]1.5synchronized和volatile的作用:[/b]

[b](1)synchronized:[/b]确保每次只有一个线程可以执行受(synchronized)保护的代码;确保一个线程更改的数据对于其他线程可见

(2)[b]volatile:[/b]比同步更简单,只适合于控制对基本变量(整数、布尔变量等)的单个实例的访问。当一个变量被声明成 volatile,任何对该变量的写操作都会绕过高速缓存,直接写入主内存,而任何对该变量的读取也都绕过高速缓存,直接取自主内存。这表示所有线程在任何时候看到的 volatile 变量值都相同。


[b]1.6理解同步锁synchronized:[/b]不是代码块本身被锁住,而是同一个对象在不同的线程里面,谁持有锁,才能执行被锁保护的代码块。如果是两个不同的对象,那么有synchronized标志的代码块,对他们而言,没有意义。


[b]1.7哪些地方不需要同步:[/b]

· 由静态初始化器(在静态字段上或 static{} 块中的初始化器)初始化数据时
· 访问 final 字段时
· 在创建线程之前创建对象时
· 线程可以看见它将要处理的对象时


[b]1.8守护线程和非守护线程:[/b]每一个Java程序都由 主线程+自己创建的线程+守护线程构成,所谓守护线程就是隐藏的系统线程,如垃圾收集线程、JVM创建的其它线程等,Java程序退出之后,守护线程还在运行。可以调用Thread.setDaemon(boolean flag)方法将自己创建的线程声明为守护线程。


[b]2.创建简单的多线程程序实例:[/b]银行ATM存取款


2.1银行账号类

package com.sun.yli.thread;

/**
 * 账户UserAccount
 * @author yli
 */
public class UserAccount {

	private String user;

	private int balance;

	public UserAccount(String user, int balance) {
		this.user = user;
		this.balance = balance;
	}

	public void drawMoney(int money) {
		if (money > this.balance) {
			System.out.println("invalid number of drawMoney");
			return;
		}
		this.balance -= money;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	public void dispaly() {
		System.out.println(this.user + " has balance:" + this.balance);
	}

}




2.2存款实例类


package com.sun.yli.thread;

/**
 * 存款实例
 * @author yli
 */
public class UserDeposit extends Thread {

	private UserAccount user;
	private int money;

	public UserDeposit(UserAccount user, int money) {
		this.user = user;
		this.money = money;
	}

	@Override
	public void run() {
		// 账号使用同步锁
		synchronized (user) {
			int balance = user.getBalance();
			user.setBalance(balance + this.money);
			try {
				// 假设存款花费0.1秒
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("当前余额" + balance + "元;存入" + money + "元,最终余额"
					+ user.getBalance() + "元");
		}
	}
}




2.3取款实例类


package com.sun.yli.thread;

/**
 * 取款实例
 * @author yli
 */
public class UserDrawMoney extends Thread {

	private UserAccount user;
	private int money;

	public UserDrawMoney(UserAccount user, int money) {
		this.user = user;
		this.money = money;
	}

	@Override
	public void run() {
		// 账号使用同步锁
		synchronized (user) {
			int balance = user.getBalance();
			if (money > balance) {
				return;
			}
			user.setBalance(balance - money);
			try {
				// 假设取款花费0.1秒
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("当前余额" + balance + "元;取款" + money + "元,最终余额"
					+ user.getBalance() + "元");
		}
	}
}




2.4测试


package com.sun.yli.thread;

/**
 * 测试
 * @author yli
 */
public class UserBankTest {

	public static void main(String[] args) {

		UserAccount user = new UserAccount("suning", 1000);

		// 取款 150
		new UserDrawMoney(user, 100).start();

		// 存入 100
		new UserDeposit(user, 100).start();

		// 取款 50
		new UserDrawMoney(user, 100).start();

		// 存入 200
		new UserDeposit(user, 100).start();
	}

}