前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java并发编程之ReadWriteLock,读取大数据的利器

Java并发编程之ReadWriteLock,读取大数据的利器

作者头像
张拭心 shixinzhang
发布2022-05-06 15:43:11
1870
发布2022-05-06 15:43:11
举报

现在都是“大数据”时代,大量的用户数据需要处理,如何保证大量数据在多线程下的安全,成了比较重要的问题。

今天要学习的就是java.util.concurrent包下Locks接口的一个实现类,ReadWriteLock,读写锁。

读写锁的出现是为了弥补传统同步方式synchronized的缺憾,使用synchronized同步的方法或语句,当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间。

代码如下:

代码语言:javascript
复制
/**
 * 读写锁 : 在读写大数据时有效提高效率<br>
 * 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
 * @author sxzhang
 * @since 2015/8/21 9:23
 *
 */
public class ReadWriteTest {

	public static void main(String[] args) {
		final Data data  = new Data();
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					data.setData(new Random().nextInt(30));
				}
			}).start();
		}
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					data.getData();
				}
			}).start();
		}
	}

}

/**
 * 使用synchronized同步的类<br>
 * 当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间
 * @author sxzhang
 *
 */
class Data{
	private int data;	//共享资源
	
	public synchronized void setData(int data) {
		String threadName = Thread.currentThread().getName();	
		System.out.println(threadName + "准备写数据:--->");
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.data = data;
		System.out.println(threadName + "写入 " + this.data + "完毕 --->");
	}

	public synchronized void  getData() {
		String threadName = Thread.currentThread().getName();	
		System.out.println(threadName + "准备读取数据:<---");
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(threadName + "读取数据 " + this.data + "完毕  <---");
	}

	
}
代码语言:javascript
复制
</pre><span style="font-size:18px">为了模拟大数据,我们把每次读取的时间延长一些。</span><p></p><p><span style="font-size:18px">运行结果:</span></p><p><img src="https://img-blog.csdn.net/20150821100455408?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p><span style="font-size:18px">可以看到,不管每个线程读取数据耗时多长,同时只能有一个线程读取数据,其他数据都被阻塞,等待当前线程结束后才能访问。</span></p><p><span style="font-size:18px"></span></p><p><span style="font-size:18px">而使用读写锁后,多个线程同时读取时,可以并发执行,不会阻塞。</span></p><p><span style="font-size:18px">代码如下:</span></p><p></p><pre name="code" class="java">/**
 * 读写锁 : 在读写大数据时有效提高效率<br>
 * 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
 * @author sxzhang
 * @since 2015/8/21 9:23
 *
 */
public class ReadWriteTest {

	public static void main(String[] args) {
		final Data1 data  = new Data1();
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					data.setData(new Random().nextInt(30));
				}
			}).start();
		}
		for (int i = 0; i < 3; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					data.getData();
				}
			}).start();
		}
	}

}

/**
 * 使用读写锁同步的类<br>
 * 多个线程同时读取时,可以并发执行,不会阻塞
 * @author sxzhang
 *
 */
class Data1{
	private int data;	//共享资源
	//Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
	//默认不公平,指的是,阻塞时间长的线程不一定先获取被释放的资源
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	public void setData(int data) {
		rwl.writeLock().lock();			//記得用完及時釋放锁
		try{
			String threadName = Thread.currentThread().getName();	
			System.out.println(threadName + "准备写数据:--->");
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.data = data;
			System.out.println(threadName + "写入 " + this.data + "完毕 --->");
		}finally{
			rwl.writeLock().unlock();	//release the writeLock
		}
	}

	public void getData() {
		rwl.readLock().lock();
		try{
			String threadName = Thread.currentThread().getName();	
			System.out.println(threadName + "准备读取数据:<---");
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(threadName + "读取数据 " + this.data + "完毕 <---");
		}finally{
			rwl.readLock().unlock();
		}
	}
}

运行结果:

可以看到,线程3、4、5同时读取数据,这样就比synchronized节省不少时间。

要学习java并发编程,java.util.concurrent包下的内容还要好好学习

(学习参考自http://blog.csdn.net/ghsau/article/details/7461369/#comments,谢谢这位前辈)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档