JUC-浅谈sleep、wait、yield

sleep

sleep 方法是属于 Thread 类中的,sleep 过程中线程不会释放锁,只会阻塞线程,让出cpu给其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态,可中断,sleep 给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会。sleep时间过后,线程会进入就绪态,等待系统调度,如果此时系统资源请允许(CPU等各种需要的资源),线程就进入运行态继续执行后续程序。

wait

wait 方法是属于 Object 类中的,wait 过程中线程会释放对象锁,只有当其他线程调用 notify 才能唤醒此线程。wait 使用时必须先获取对象锁,即必须在 synchronized 修饰的代码块中使用,那么相应的 notify 方法同样必须在 synchronized 修饰的代码块中使用,如果没有在synchronized 修饰的代码块中使用时运行时会抛出IllegalMonitorStateException的异常。wait 方法是实例方法(非 static 方法),因此不能在 static 中使用。

yield

和 sleep 一样都是 Thread 类的方法,都是暂停当前正在执行的线程对象,不会释放资源锁,和 sleep 不同的是 yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。还有一点和 sleep 不同的是 yield 方法只能使同优先级或更高优先级的线程有执行的机会。

总结

  1. 所属类不同:wait()是Object类中的非静态方法;sleep()、yield()是Thread类中的静态方法。

  2. 作用不同:wait()用于线程同步或者线程之间进行通信;sleep()用于休眠当前线程,并在指定的时间点被自动唤醒;yield()临时暂停当前正在执行的线程,来让有同样优先级的正在等待的线程有机会执行(如果等待的线程优先级较低,则当前线程继续执行)。

  3. 释放资源:wait()释放对象锁;sleep()不释放对象锁,抱着锁睡觉;yield()仅释放线程所占用的CPU,锁资源不会释放。

  4. 应用场景不同:wait()适用于同步代码块中;sleep()休眠当前线程,应用场景没有限制;yield()暂停当前线程,应用场景也没有限制。

  5. 被唤醒后的状态不同:wait()被notify()或者notifyAll()唤醒后,先进入阻塞状态(尝试获得锁),然后进入就绪状态;sleep()被唤醒后,进入就绪状态;yield()不需要唤醒,一直处于就绪状态,获得CPU后继续运行。


PageHelper分页查询优化

描述:
在项目中使用Mybatis分页插件分页查询十分缓慢,但是在数据库中执行速度却很快?
该数据库的表共有10000条数据,分页查询时,在数据库中是很快,但是在使用Mybatis分页插件的时候居然8s多!

原因:
PageHelper在做分页查询的时候,select count(0) 会先把原来的查询语句全部重新查询一遍(未做数量限制),然后再执行select count(0)操作,相当于查询两遍,导致查询速度慢。

例如:

1
select count(*) from ("原来的查询sql,相当于多查了一遍") user

优化方案:
在原来的查询方法后面,加上”_COUNT”,重写总数量查询方法,优化sql,覆盖默认的数量查询方法。

例如原来的mapper接口里面的查询方法:

1
Page<Map<String, Object>> getOrderInfo(Map<String, Integer> map);

现在重写一个方法,getOrderInfo后面加“_COUNT”:返回类型必须为Long

1
2
3
4
5
6
7
8
<select id="getOrderInfo" resultType="Long" useCache="false">
...
</select>
<select id="getOrderInfo_COUNT" resultType="Long" useCache="false">
SELECT
COUNT(1)
FROM t1
</select>

总结:
分页插件中的计算Count的sql语句,会将需要分页的所有数据查出来然后生成一个临时表,再去计算Count。如果数据量比较大,生产临时表就多查询了一次表,会导致最后Count计算会十分慢,从而影响分页的结果。


RBAC的基本概念

概念

RBAC即Role Based Access Control,意为基于角色的访问控制。用户与角色相关联,当用户在系统进行注册时可以选择成为某一角色从而拥有这个角色的权限,当然新注册的用户的权限也可以由上一级用户授予如管理员认定某个用户为某个角色就授予了该普通用户对应角色得权限。用户与权限的逻辑分离极大地简化了权限的管理。

权限管理问题

在没有进行权限划分的页面中,所有登录的用户看到的页面内容都是一致的。但在实际业务运用中,每个页面应该有公共的部分即每个用户都能看到的部分以及某一类用户自己才能看见的部分如系统的管理员能看到管理普通用户的页面而普通用户只能看到对他提供服务的页面。毫无疑问,此时不同的用户登录系统以后他们所看到的内容以及执行的操作是有区别的。

权限的使用场景

  • 不同用户登录后看到的菜单不一样

  • 不同用户登录后看到的表单数据不一样

  • 不同用户登录后能操作的功能不一样

总结

在进行web项目开发时,使用RBAC的思想来设计数据库表。在设计数据库表时我们通常要进行逻辑数据表的设计以及功能资源表的设计,不同的用户登录web页面看到不一样的内容即是查询了功能资源表里的不同记录。使用RBAC思想设计的方案是非常灵活的。