本帖最后由 上篮高手 于 2013-10-19 12:01 编辑
1: 最简单也是最常用的: 使用方法实现线程同步
所谓同步方法,即有Syschronized 关键字修饰的方法。其原理是通过java的内置锁实现的,其实每个
java 对象都有一个内置锁,如果方法用此关键字声明了,该内置锁会保护整个方法。
例子如下:
这是一个银行类: 负责往里头存钱 ,和 查询当前存款。- private class Bank {
- private int account = 100;// 每个账户的初始金额是100元
-
- public synchronized void deposit(int money) {// 向账户中存入money元
- account += money;
- }
-
- public int getAccount() {// 查询账户余额
- return account;
- }
- }
复制代码 这是个继承Runnable 的Trannsfer类: 这是一个带传入参数的- private class Transfer implements Runnable {
- private Bank bank;
- private JTextArea textArea;
-
- public Transfer(Bank bank, JTextArea textArea) {// 初始化变量
- this.bank = bank;
- this.textArea = textArea;
- }
-
- public void run() {
- for (int i = 0; i < 10; i++)
复制代码 这是线程的运行如下:- Bank bank = new Bank();
- Thread thread1 = new Thread(new Transfer(bank, thread1TextArea));
- thread1.start();
- Thread thread2 = new Thread(new Transfer(bank, thread2TextArea));
- thread2.start()
复制代码 打印结果如下:
一线程:
账户的余额是:110
账户的余额是:130
账户的余额是:160
账户的余额是:180
账户的余额是:200
账户的余额是:210
账户的余额是:230
账户的余额是:260
账户的余额是:280
账户的余额是:300
二线程:
账户的余额是:120
账户的余额是:140
账户的余额是:150
账户的余额是:170
账户的余额是:190
账户的余额是:220
账户的余额是:240
账户的余额是:260
账户的余额是:270
账户的余额是:290
2: 使用代码块实现线程的同步:
Syschonized 不仅可以修饰方法,还可以修饰代码块。
格式为: syschronized(objcect) {}
还是刚才的例子:修改如下:- private class Bank {
- private int account = 100;
-
- public void deposit(int money) {
- synchronized (this) {// 获得Bank类的锁 *******注意了
- account += money;
- }
- }
-
- public int getAccount() {
- return account;
- }
- }
复制代码 3: 使用特殊变量实现线程同步:
volatile 关键字为域变量提供了一种免锁机制。使用这个关键字相当于告诉虚拟机该变量可能会被其他线程修改,因此每次使用该变量时就要
更新计算,而不是使用寄存器里头的值。它不能用来修饰final 类型的变量。
还是刚才的例子:- private class Bank {
- private volatile int account = 100;// 将域变量用volatile修饰 *******注意了
-
- public void deposit(int money) {// 向账户中存钱
- account += money;
- }
-
- public int getAccount() {// 获得账户余额
- return account;
- }
- }
复制代码 4: 使用重入锁实现线程的同步:
java se 5.0 增加了一个java.util.comcurrent 包来支持同步。
ReentrantLock类是可重入 互斥 实现了Lock接口的锁。
方法有:
ReentrantLock() 无参构造函数,创建一个实例
lock() 获得锁
unlock() 释放锁。
应用如下:- private class Bank {
- private int account = 100;// 账户的初始金额是100
- private Lock lock = new ReentrantLock();// 创建重入锁对象 **********注意了
-
- public void deposit(int money) {
- lock.lock();// 打开锁
- try {
- account += money;
- } finally {
- lock.unlock();// 关闭锁
- }
- }
-
- public int getAccount() {// 查看余额
- return account;
- }
- }
复制代码 5: 使用线程局部变量实现线程同步:
类: ThreadLocal 来管理变量,则每个使用该变量的线程都会获得该变量的副本,副本之间相互独立,这样每个线程都
可以随意修改自己的副本,而不会对其他线程产生影响。
方法如下:
ThreadLocal () 无参构造函数
get() 返回当前线程副本中的值
initialValue() 返回当前线程的初始值。
set(T value) 设置副本中的值。
应用如下:
发现account变量用new ThreadLocal<Integer>() 来创建了- public class Bank {
- // 使用ThreadLocal类来管理共享变量account
- private static ThreadLocal<Integer> account = new ThreadLocal<Integer>() { //*******注意
- @Override
- protected Integer initialValue() {
- return 100;// 重写initialValue()方法,将account的初始值设为100
- }
- };
-
- public void deposit(int money) {
- account.set(account.get() + money);// 利用account的get()、set()方法实现存钱 //*******注意
- }
-
- public int getAccount() {// 获得账户余额
- return account.get(); //*******注意
- }
- }
复制代码 总结: 以上5中方法实现同步,大家可以任选自己喜欢的方法。
|