//Lock 锁的例子:和synchronized效果类似。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest8 {
//Lock用来代替synchronized。
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new LockTest8().init();
//多线程代码块中(run方法内)要做到互斥效果,需要用到同一个对象锁.
}
/**
* 打印字符类
*/
class OutPutToScreen{
//产生一把锁.
Lock lock = new ReentrantLock();
public void print(String string){
//锁住
lock.lock();
try {
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
}finally{
//解锁
//unlock放在finally里比较好。以防发生异常时候没有释放锁.
lock.unlock();
}
}
}
/**
* run方法里面操作的是同一个对象。因此用到当前对象锁,当前对象在被线程占用时,其他线程无法操作。
*/
public void init(){
OutPutToScreen print = new OutPutToScreen();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
print.print("tom_and_jerry");
}
}
}).start();
}
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest8_1 {
public static void main(String[] args) {
//(用两个线程)实现向屏幕打印两个字符串,tom jerry。
new LockTest8_1().init();
}
Lock lock = new ReentrantLock();
/**
* 打印字符类
*/
class OutPutToScreen{
//互斥效果一定要是同一个对象,这个例子中A线程用到OutPutToScreen print对象,B
public void print(String string){
lockTest(string);
}
public void print2(String string){
lockTest(string);
}
public void lockTest(String string){
lock.lock();
try {
int len = string.length();
for(int i=0;i<len;i++){
System.out.print(string.charAt(i));
}
System.out.println();
} finally{
lock.unlock();
}
}
}
public void init(){
OutPutToScreen print = new OutPutToScreen();
OutPutToScreen print2 = new OutPutToScreen();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//线程操作不同对象
print.print("thread_test");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
//线程操作不同对象
print2.print("tom_and_jerry");
}
}
}).start();
}
}
// 读写锁。的例子介绍
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.xml.crypto.Data;
public class LockReadWriteTest {
public static void main(String[] args) {
//读写锁测试。读和写要互斥,读和读不用互斥,写和写要互斥,这个是基本的规则
//共享数据封装在一个类中。
LockReadWriteTest test = new LockReadWriteTest();
test.test();
}
public void test(){
MyData data = new MyData();
Random r =new Random();
//3个线程负责读
for(int i=0;i<3;i++){
new Thread(new Runnable() {
@Override
public void run() {
while(true){
data.read();
}
}
}).start();
}
//3个线程负责写
for(int i=0;i<3;i++){
new Thread(new Runnable() {
@Override
public void run() {
while(true){
data.write(r.nextInt(1000));
}
}
}).start();
}
}
class MyData{
//读写锁:读和写操作互斥。
ReadWriteLock lock = new ReentrantReadWriteLock();
private Object data = null;
//读
public void read() {
//
lock.readLock().lock();
try {
System.out.println("准备读...");
Thread.sleep(100);
System.out.println("读取完毕:"+this.data);
}catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.readLock().unlock();
}
}
//写
public void write(int data){
lock.writeLock().lock();
try {
System.out.println("准备写...");
Thread.sleep(100);
this.data = data;
System.out.println("写入完毕:"+this.data);
}catch (InterruptedException e) {
e.printStackTrace();
} finally{
lock.writeLock().unlock();
}
}
}
}
//读写锁API中的例子
class CachedData {
Object data;//缓存数据
volatile boolean cacheValid;//缓存是否存在
//读写锁
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
//阅读这段代码时先考虑缓存常用的操作,那就是频繁读取,其次处理写入操作。
//并发的时候多个线程读的话不会造成数据的破坏,所以先上读锁,如果没有数据可读,就会有一个线程开始写入数据,
//并且给上 上写锁,在写之中不能读。写完了以后还原为读锁。这样读和写之间可以到达互斥效果。
void processCachedData() {
//0 读锁:当读取缓存数据时,不能有写入操作。
rwl.readLock().lock();
//3当没有缓存时候,就是写入缓存操作了
if (!cacheValid) {
// Must release read lock before acquiring write lock
//4在写入前先释放读锁。
rwl.readLock().unlock();
//5接着在写入时候上 写锁
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
//6在写之前再次判断一下是否写入数据或者更改数据了。因为还有可能有线程拿到写锁.
if (!cacheValid) {
//7写入数据
data = ...
//8更改标记位
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
//9在写入操作最后 在上 上读锁
rwl.readLock().lock();
} finally {
//10在写入操作最后释放写锁
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
try {
//1 读取数据即可
use(data);
} finally {
//2 最后释放读锁
rwl.readLock().unlock();
}
}
}}