java5线程框架Executor_读写锁的例子

        java5线程框架Executor 读写锁的例子

  为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他 的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。 ReadWriteLock 可满足这种需要。 ReadWriteLock 内置两个 Lock ,一个是读的 Lock ,一个是写的 Lock 。多个线程可同时得到读的 Lock ,但只有一个线程能得到写的 Lock ,而且写的 Lock 被锁定后,任何线程都不能得到 Lock 。

 

  这里模拟了这样一个场景: 在ReadWriteLockOperator对象里设置一个共享资源 shareResources 。
                          有3个读者(A, B, C)一直连续的从 shareResources 获取信息, 然后输出到

                          控制台 ;有一个作者每隔60秒往 shareResources 加入信息, 加信息的过程

                          相对耗时, 在这段时间, 任何读者都不能访问 shareResources。

 

  写了4个类来验证这种情况,只在windows下做了测试。
  1.1、 ReadTask.java       读任务
  1.2、 WriteTask.java      写任务
  1.3、 ReadWriteLockLogic.java     读写操作的逻辑
  1.4、 ReadWriteLockTest.java      带有main方法的测试类


=================  1.1 ReadTask.java =====================
package Executor;
//可执行任务
public class ReadTask extends Thread {
  //logic bean
  private ReadWriteLockLogic readWriteLockOperator;
 
  //读者
  private String reader;

  public ReadTask(ReadWriteLockLogic readWriteLockOperator, String reader) {
    this.readWriteLockOperator = readWriteLockOperator;
    this.reader = reader; 
  }
 
  private ReadTask(){}

  // 执行任务
  public void run() {
    if(this.readWriteLockOperator != null){
      try {
        while(!isInterrupted()){
          Thread.sleep(200);
          System.out.println(reader + " read:" + Thread.currentThread().toString() + " : " + this.readWriteLockOperator.read());
        }
      } catch (Exception e) {
        // TODO: handle exception
      }
    }
  }
}
=========================  1.1 end ========================

 

=================  1.2 WriteTask.java =====================
package Executor;
//可执行任务
public class WriteTask  extends Thread{
  //logic bean
  private ReadWriteLockLogic readWriteLockOperator;
 
  //作者
  private String writer;
 
  public WriteTask(ReadWriteLockLogic readWriteLockOperator, String writer) {
    this.readWriteLockOperator = readWriteLockOperator;
    this.writer = writer;
  }
 
  private WriteTask(){}

  // 一个很耗时的写任务
  public void run() {
    try {
      while(!isInterrupted()){
        Thread.sleep(100);
        this.readWriteLockOperator.write(this.writer, "hehehhe");
      }
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
}
=========================  1.2 end ==========================

 

=================  1.3 ReadWriteLockLogic.java ==============
package Executor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

//读写操作的逻辑
public class ReadWriteLockLogic {
  // 初始化一个 ReadWriteLock
  private ReadWriteLock lock = new ReentrantReadWriteLock();
 
  //共享资源
  private List<String> shareResources = new ArrayList<String>(0);
 
  //读
  public String read() {

    // 得到 readLock 并锁定
    Lock readLock = lock.readLock();

    readLock.lock();

    try {
      // 读相对省时,做空循环 大约0.5second
      for(int i=0 ;i<2500000; i++){
        System.out.print("");
      }

      // 做读的工作
      StringBuffer buffer = new StringBuffer();
      for (String shareResource : shareResources) {
        buffer.append(shareResource);
        buffer.append("/t");       
      }

      return buffer.toString();

    } finally {
      readLock.unlock();//一定要保证锁的释放
    }
  }

  //写
  public void write(String writer, String content) {

    // 得到 writeLock 并锁定
    Lock writeLock = lock.writeLock();

    writeLock.lock();

    try {
      System.out.println(writer + " write ===" + Thread.currentThread().toString());
      // 写比较费时,所以做空循环 大约13second
      for(int i=0 ;i<50000000; i++){
        System.out.print("");
        System.out.print("");
      }
     
      // 做写的工作
      int count = shareResources.size();
      for (int i=count; i < count + 1; i++) {
        shareResources.add(content + "_" + i);
      }

    } finally {
      writeLock.unlock();//一定要保证锁的释放
    }
  }
}
=========================  1.3 end ==========================

 

=================  1.4 ReadWriteLockTest.java ===============
package Executor;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ReadWriteLockTest {
  public static void main(String[] args) throws InterruptedException, ExecutionException {

    //1 创建一个具有排程功能的线程池
    ScheduledExecutorService service = Executors.newScheduledThreadPool(5);

    //2 读写锁的logic bean
    ReadWriteLockLogic lockOperator = new ReadWriteLockLogic();

    //3 生成一个可执行任务(该任务执行完毕可以返回结果 或者 抛出异常;而Runnable接口的run方法则不行)
    Runnable writeTask1 = new WriteTask(lockOperator, "作者A");

    //4 延时0秒后每2秒重复执行writeTask1;
    service.scheduleAtFixedRate(writeTask1, 0, 60, TimeUnit.SECONDS);

    //5 创建3个读任务
    Runnable readTask1 = new ReadTask(lockOperator, "读者A");
    Runnable readTask2 = new ReadTask(lockOperator, "读者B");
    Runnable readTask3 = new ReadTask(lockOperator, "读者C");

    //6 延时0秒后 每秒执行一次task1;
    service.scheduleAtFixedRate(readTask1, 1, 1, TimeUnit.SECONDS);
    service.scheduleAtFixedRate(readTask2, 2, 1, TimeUnit.SECONDS);
    service.scheduleAtFixedRate(readTask3, 3, 1, TimeUnit.SECONDS);
   
  }
}
=========================  1.4 end ==========================

 

输出示例:
作者A write ===Thread[pool-1-thread-1,5,main]
读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 
读者B read:Thread[pool-1-thread-4,5,main] : hehehhe_0 
读者A read:Thread[pool-1-thread-2,5,main] : hehehhe_0 
读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 
读者B read:Thread[pool-1-thread-4,5,main] : hehehhe_0 
读者B read:Thread[pool-1-thread-4,5,main] : hehehhe_0 
读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 
读者A read:Thread[pool-1-thread-2,5,main] : hehehhe_0 
作者A write ===Thread[pool-1-thread-1,5,main]
读者B read:Thread[pool-1-thread-4,5,main] : hehehhe_0 hehehhe_1 
读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 hehehhe_1

一旦有 "作者A write === ..." 在后台输出,表明开始了写操作, 在写过程中读者处于等待中, 后台无输出, 直到写任务执行完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值