A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 上篮高手 于 2013-10-19 12:01 编辑

1:  最简单也是最常用的: 使用方法实现线程同步

       所谓同步方法,即有Syschronized 关键字修饰的方法。其原理是通过java的内置锁实现的,其实每个
       java 对象都有一个内置锁,如果方法用此关键字声明了,该内置锁会保护整个方法。

       例子如下:

       这是一个银行类: 负责往里头存钱 ,和 查询当前存款。
  1. private class Bank {
  2.         private int account = 100;// 每个账户的初始金额是100元
  3.         
  4.         public synchronized void deposit(int money) {// 向账户中存入money元
  5.             account += money;
  6.         }
  7.         
  8.         public int getAccount() {// 查询账户余额
  9.             return account;
  10.         }
  11.     }
复制代码
这是个继承Runnable 的Trannsfer类: 这是一个带传入参数的
  1.   private class Transfer implements Runnable {
  2.         private Bank bank;
  3.         private JTextArea textArea;
  4.         
  5.         public Transfer(Bank bank, JTextArea textArea) {// 初始化变量
  6.             this.bank = bank;
  7.             this.textArea = textArea;
  8.         }
  9.         
  10.         public void run() {
  11.             for (int i = 0; i < 10; i++)
复制代码
这是线程的运行如下:
  1. Bank bank = new Bank();
  2.         Thread thread1 = new Thread(new Transfer(bank, thread1TextArea));
  3.         thread1.start();
  4.         Thread thread2 = new Thread(new Transfer(bank, thread2TextArea));
  5.         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)  {}

     还是刚才的例子:修改如下:
  1.   private class Bank {
  2.         private int account = 100;
  3.         
  4.         public void deposit(int money) {
  5.             synchronized (this) {// 获得Bank类的锁 *******注意了
  6.                 account += money;
  7.             }
  8.         }
  9.         
  10.         public int getAccount() {
  11.             return account;
  12.         }
  13.     }
复制代码
3: 使用特殊变量实现线程同步:
       volatile 关键字为域变量提供了一种免锁机制。使用这个关键字相当于告诉虚拟机该变量可能会被其他线程修改,因此每次使用该变量时就要
       更新计算,而不是使用寄存器里头的值。它不能用来修饰final 类型的变量。

        还是刚才的例子:
  1. private class Bank {
  2.         private volatile int account = 100;// 将域变量用volatile修饰 *******注意了
  3.         
  4.         public void deposit(int money) {// 向账户中存钱
  5.             account += money;
  6.         }
  7.         
  8.         public int getAccount() {// 获得账户余额
  9.             return account;
  10.         }
  11.     }
复制代码
4: 使用重入锁实现线程的同步:

       java se 5.0 增加了一个java.util.comcurrent  包来支持同步。
       ReentrantLock类是可重入  互斥  实现了Lock接口的锁。

        方法有:
                   ReentrantLock()   无参构造函数,创建一个实例
                   lock()     获得锁
                   unlock()   释放锁。


        应用如下:
  1.    private class Bank {
  2.         private int account = 100;// 账户的初始金额是100
  3.         private Lock lock = new ReentrantLock();// 创建重入锁对象  **********注意了
  4.         
  5.         public void deposit(int money) {
  6.             lock.lock();// 打开锁
  7.             try {
  8.                 account += money;
  9.             } finally {
  10.                 lock.unlock();// 关闭锁
  11.             }
  12.         }
  13.         
  14.         public int getAccount() {// 查看余额
  15.             return account;
  16.         }
  17.     }
复制代码
5: 使用线程局部变量实现线程同步:


        类: ThreadLocal   来管理变量,则每个使用该变量的线程都会获得该变量的副本,副本之间相互独立,这样每个线程都
        可以随意修改自己的副本,而不会对其他线程产生影响。
   
         方法如下:
                ThreadLocal  () 无参构造函数
                get() 返回当前线程副本中的值
                initialValue() 返回当前线程的初始值。
                set(T value) 设置副本中的值。




           应用如下:
            
          发现account变量用new ThreadLocal<Integer>() 来创建了
  1. public class Bank {
  2.     // 使用ThreadLocal类来管理共享变量account
  3.     private static ThreadLocal<Integer> account = new ThreadLocal<Integer>() {  //*******注意
  4.         @Override
  5.         protected Integer initialValue() {
  6.             return 100;// 重写initialValue()方法,将account的初始值设为100
  7.         }
  8.     };
  9.    
  10.     public void deposit(int money) {
  11.         account.set(account.get() + money);// 利用account的get()、set()方法实现存钱 //*******注意
  12.     }
  13.    
  14.     public int getAccount() {// 获得账户余额
  15.         return account.get(); //*******注意
  16.     }
  17. }
复制代码
总结:            以上5中方法实现同步,大家可以任选自己喜欢的方法。

     
      



评分

参与人数 1技术分 +1 收起 理由
李江 + 1 很给力!

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马