百度编辑器(ueditor)完整实例在asp项⽬实现附源码
【实例简介】
ueditor编辑器含有如下功能:
全屏源码撤销重做⽆序列表有序列表取消超链接超链接清空⽂档全选打印查询替换预览
Google地图百度地图百度应⽤分页图⽚涂鸦⾳乐附件截图表情视频插⼊Iframe模版背景⽇期时间图⽚转存⽔平线锚点特殊字符引⽤插⼊代码
加粗斜体下划线删除线⽂字颜⾊背景颜⾊上标下标居左对齐居中对齐居右对齐两端对齐字母⼤写字母⼩写从左向右输从右向左输⾸⾏缩进清除格式格式刷⾃动排版纯⽂本粘贴⾃定义样式段落格式段前间距段后间距⾏间距字体字号图⽚默认图⽚居左图⽚居右图⽚居中
插⼊表格删除表格右合并单元格下合并单元格拆分成⾏拆分成列拆成单元格合并单元格前插⼊列前插⼊⾏删除列删除⾏表格前插⾏
⾃动聚焦⼯具栏浮动字数统计表情本地化⾃动清除⾃动长⾼元素路径图⽚浮层纯⽂本粘贴源码⾼亮右键菜单
⽽且可以⾃定义插件 ⼆次开发
【实例截图】
⽂件:(访问密码:551685)
以下内容⽆关:
-------------------------------------------分割线---------------------------------------------
1. 介绍
ReentrantLock类图
结合上⾯的ReentrantLock类图,ReentrantLock实现了Lock接⼝,它的内部类Sync继承⾃AQS,绝⼤部分使⽤AQS的⼦类需要⾃定义的⽅法存在Sync中。⽽ReentrantLock有公平与⾮公平的区别,即’是否先阻塞就先获取资源’,它的主要实现就是FairSync与NonfairSync,后⾯会从源码⾓度看看它们的区别。
2. 源码剖析
Sync是ReentrantLock控制同步的基础。它的⼦类分为了公平与⾮公平。使⽤AQS的state代表获取锁的数量
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
...
}
我们可以看出内部类Sync是⼀个抽象类,继承它的⼦类(FairSync与NonfairSync)需要实现抽象⽅法lock。
下⾯我们先从⾮公平锁的⾓度来看看获取资源与释放资源的原理
故事就从就两个变量开始:
// 获取⼀个⾮公平的独占锁asp查看源码配置ui
/**
* public ReentrantLock() {
*    sync = new ReentrantLock.NonfairSync();
* }
*/
private Lock lock = new ReentrantLock();
// 获取条件变量
private Condition condition = wCondition();
2.1 上锁(获取资源)
lock.lock()
public void lock() {
sync.lock();
}
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 获取资源
final void lock() {
// 若此时没有线程获取到资源,直接设置当前线程独占访问资源。
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// AQS的⽅法
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
// 实现在⽗类Sync中
return nonfairTryAcquire(acquires);
}
}
AQS的acquire
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
上⼀节已经剖析过AQS的acquire的整个流程了,就差⼦类如何去实现tryAcquire了。
// Sync实现的⾮公平的tryAcquire
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
/
/ 此时若没有线程获取到资源,当前线程就直接占⽤该资源
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 若当前线程已经占⽤了该资源,可以再次获取该资源 ->这个⾏为就是可重⼊锁的⽀撑else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error(“Maximum lock count exceeded”);
setState(nextc);
return true;
}
return false;
}
尝试获取资源的过程是⾮常简单的,这⾥再贴⼀下acquire的流程图
acquire流程图
2.2 释放资源
lock.unlock();
public void unlock() {
// AQS的⽅法
}
AQS的release
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
release的流程已经剖析过了,接下来看看tryRelease的实现
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 这⾥可以看出若没有持有锁,就释放资源,就会报错
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
tryRelease的实现也很简单,这⾥再贴⼀下release的流程图
release流程图
2.3 公平锁与⾮公平锁的区别
公平锁与⾮公平锁,即’是否先阻塞就先获取资源’, ReentrantLock中公平与否的控制就在tryAcquire中。下⾯我们看看,公平锁的tryAcquire
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// (2.3.1)
// sync queue中是否存在前驱结点
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
区别在代码(2.3.1)
hasQueuedPredecessors
判断当前线程的前⾯有⽆其他线程排队;若当前线程在队列头部或者队列为空返回false
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
3. 总结
本⽂介绍了利⽤AQS实现的锁ReetrantLock
讲解了tryRelease与tryAcquire的实现原理
说了说锁的公平与否的实现,是否在意当前线程是否有其他线程排队

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。