理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的.

1.如何创建锁?

Lock lock = new ReentrantLock();

2.如何使用锁?

可以参看Lock文档,其使用格式如下:

class X {
private final ReentrantLock lock = new ReentrantLock();
// ... public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}

在要用的方法前加上锁,比如写操作,然后在finally中将锁打开.

这里,将前文java核心知识点学习----多线程并发之线程同步中的代码改用Lock实现数据同步,改写代码如下:

package com.amos.concurrent;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* @ClassName: LockTest
* @Description: Lock学习
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 22, 2014 1:48:36 AM
*/
public class LockTest {
public static void main(String[] args) {
new LockTest().init();
} private void init() {
final OutPuter outPuter = new OutPuter();
// 新建一个线程
new Thread(new Runnable() {
public void run() {
while (true) {
// 休息10ms
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outPuter.output("hi_amos");// 输出
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outPuter.output("amosli");
}
}
}).start();
} static class OutPuter {
// 方式1:使用synchronized关键字
// public synchronized void output(String name) {
// int length = name.length();
// for (int i = 0; i < length; i++) {
// System.out.print(name.charAt(i));
// }
// System.out.println();
// } // 方式2:使用Lock锁
Lock lock = new ReentrantLock(); public void output(String name) {
lock.lock();// 加锁
int length = name.length();
// 输出name,逐个字节读取,并输出
try {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} finally {
lock.unlock();// 解锁
}
}
}
}

3.synchronized关键字与Lock的区别?

1).Lock是Java5中的新特性,更加面向对象.更类似于生活中的锁.

2).Lock锁一般需要手动开启和关闭,而synchronized则不需要.

建议优先使用Lock.

4.注意事项:

1)多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥.

2)要实现两个线程互斥,那么要将锁加到同一个被访问对象上.

3)如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁,总之,读的时候用读锁,写的时候用写锁!

5.设计一个缓存系统

什么是缓存系统? 就是看本地是否已经缓存过此数据,如果已经缓存过,那就直接拿来用;如果没有缓存过,那就查询数据库.

下面看代码:

private Map<String, Object> cache = new HashMap<String, Object>();

    public synchronized Object getData(String key){
Object object = cache.get(key);
if (object==null) {
object = "1323";//实际是去queryDB();
}
return object;
}

这里其实是一个超级简单的缓存系统,原理就是:第一次访问的时候把值存入到cache中,第二次访问时,先去看cache中是否有值如果有值,那么就直接去取值,而不是从数据库中去取.

为什么要加上synchronized? 这是为了保持数据互斥,访问的时候不相互影响,因为其中有对object进行赋值操作,这是一个写操作,所以最好加上锁.

如何优化?

private ReadWriteLock rwl = new ReentrantReadWriteLock();
public synchronized Object getData(String key){
rwl.readLock();//read lock
Object object = cache.get(key);
try{
if (object==null) {
rwl.readLock().unlock();//释放锁
rwl.writeLock().lock();//对写加锁
try{
object = "1323";//实际是去queryDB();
}finally{
rwl.writeLock().unlock();
}
}
}finally{
rwl.readLock().unlock();
}
return object;
}

上面的代码运用到了刚学到的知识,对所有读和写进行加锁,以保持线程间的互斥,要特别注意的是要在finally中把锁打开,不管程序是否执行成功,因为如果不解锁,那么程序将会产生死锁,关于死锁,将在接下来的文章中介绍.

Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统的更多相关文章

  1. Java核心知识点学习----线程中的Semaphore学习,公共厕所排队策略

    1.什么是Semaphore? A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acq ...

  2. Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统

    理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...

  3. Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

    1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...

  4. Java核心知识点学习----线程同步工具类,CyclicBarrier学习

    线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...

  5. Java核心知识点学习----使用Condition控制线程通信

    一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A-> ...

  6. java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器

    多线程并发就像是内功,框架都像是外功,内功不足,外功也难得精要. 1.进程和线程的区别 一个程序至少有一个进程,一个进程至少有一个线程. 用工厂来比喻就是,一个工厂可以生产不同种类的产品,操作系统就是 ...

  7. java核心知识点学习----重点学习线程池ThreadPool

    线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...

  8. Java核心知识点学习----多线程 倒计时记数器CountDownLatch和数据交换的Exchanger

    本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger. 一.CountDownLatch 1.什么是Coun ...

  9. java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解

    线程内的数据共享与对象独立,举例:张三给李四转钱,开启A线程去执行转钱这个动作,刚好同时王五给赵六转钱,开启B线程去执行转钱,因为是调用的同样一个动作或者说对象,所以如果不能保证线程间的对象独立,那么 ...

随机推荐

  1. SQL总结(二)连表查询

    ---恢复内容开始--- SQL总结(二)连表查询 连接查询包括合并.内连接.外连接和交叉连接,如果涉及多表查询,了解这些连接的特点很重要. 只有真正了解它们之间的区别,才能正确使用. 1.Union ...

  2. Dos命令完成文件拷贝

    Dos命令初阶--文件拷贝 1.XCOPY命令 可以在cmd中录入:XCOPY /? 即可查看帮助 帮助: XCOPY Microsoft Windows [版本 6.2.9200] (c) 2012 ...

  3. perl读取文件

    1)文件读取的3中方法   按行读,存入标量 while (<FILE>) { print; } 按行读,存入数组 @array = <FILE>; 读入整个文件 ,存入标量 ...

  4. MVC:上传文件时限制文件类型

    之前写过一篇:MVC:上传文件 今天补充下一个功能:如何限制上传文件类型 文件类型可以在前段限制,但是太容易被绕过,最好还是在后端处理. 修改upload方法代码: [HttpPost] public ...

  5. 【uTenux实验】中断处理

    中断处理是一个比较有意思的东西.uTenux的中断处理包括了处理外部中断.CPU异常等.他是OS中任务无关部分.因此,当中断到来的时候OS会停止任务调度,不会发生任务切换.直到程序从中断中返回. uT ...

  6. C Primer Plus(第五版)12

    第 12 章 存储类, 链接和内存管理 在本章中你将学习下列内容 . 关键字: auto, extern, static, register, const, volatile, restricted. ...

  7. DataGridView控件的各种操作总结

    一.单元格内容的操作 *****// 取得当前单元格内容 Console.WriteLine(DataGridView1.CurrentCell.Value); // 取得当前单元格的列 Index ...

  8. Squid服务日志分析

    Squid服务日志分析 Apache 和 Squid 是两种著名的代理缓存软件,但Squid 较 Apache 而言是专门的代理缓存服务器软件,其代理缓存的功能强大,支持 HTTP/1.1 协议,其缓 ...

  9. input元素垂直居中

    chrome,firefox,safari, ie9+ 会根据高度自动居中文字: IE9- 以下用这段代码垂直居中: input[type="text"] { line-heigh ...

  10. Entity Framwork(EF) 7——在现在数据库的甚而上开发MVC 新项目

    一.开发背景: 由于老系统已经无法满足实际业务需求,需在现有数据库的甚而上开发新的项目. 二.困难点: 而EF默认情况下是要删除现有数据库表格后重新创建,这是不允许的.当你创建数据库对象时系统会提示“ ...