java多线程Lock关键字、Condition
一、Lock关键字相对于传统锁synchronized更加面向对象
1、示例:在多线程情况下,按顺序输出指定字符串
定义一个类专门用于输出字符串
public class ThreadLockDemo {
int len = s.length();
for (int i = 0; i < len; i++) {
System.out.print(s.charAt(i));
}
System.out.println();
}
}
多线程访问:
public static void main(String[] args) {
ThreadLockDemo threadLockDemo = new ThreadLockDemo();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadLockDemo.printLetter("liucui");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadLockDemo.printLetter("wuchengfeng");
}
}
}).start();
}
输出结果:
wuchengfenliucuig
liucui
wuchengfeng
wuchengfeng
liucui
wluiucui
chengfeng
wuchengfeng
liucui
wliucuuchengfeng
i
liucui
wuchengfeng
wliucui
uchengfeng
wucliucuihengf
eng
wluiucui
chengfeng
由控制台输出可以看出,printLetter方法在多线程访问下被打断,导致输出混乱,这时候使用lock关键字可以有效的解决这个问题
重新改写ThreadLockDemo
public class ThreadLockDemo {
Lock lock = new ReentrantLock();
public void printLetter(String s) {
//加锁
lock.lock();
try {
int len = s.length();
for (int i = 0; i < len; i++) {
System.out.print(s.charAt(i));
}
System.out.println();
} finally {
//锁释放
lock.unlock();
}
}
}
liucui
wuchengfeng
liucui
wuchengfeng
liucui
wuchengfeng
wuchengfeng
liucui
liucui
wuchengfeng
liucui
wuchengfeng
wuchengfeng
liucui
liucui
二、ReadWriteLock读写锁,共享数据的时候,多个线程只有一个线程可以写数据,多个线程可以读数据
public class ThreadLockDemo {
ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
public void readData() {
//保证多个线程可以同时读数据
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName()+"------------开始读数据--------------------------");
try {
Thread.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"------------数据读完了--------------------------");
readWriteLock.readLock().unlock();
}
public void writeData() {
//保证多个线程同时只有一个线程可以写数据
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName()+"#############开始写数据#############-");
try {
Thread.sleep((long)Math.random()*1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"#############数据写完了#############");
readWriteLock.writeLock().unlock();
}
}
三、Condition替换传统的wait、notify功能
static class ThreadSubMain {
private boolean isWait = true;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
/// 子线程循环20次
void subExcute(int i) {
lock.lock();
while (!isWait) {
try {
condition.await();//类似this.wait()
} catch (Exception e) {
e.printStackTrace();
}
}
for (int j = 0; j < 2; j++) {
System.out.println("第" + i + "个,第" + j + "子线程--->" + Thread.currentThread().getName());
}
// 当子线程执行两次后,改变标识符,唤醒主线程执行;
isWait = false;
condition.signal();
lock.unlock();
}
/// 主线程循环10次
void mainExcute() {
lock.lock();
for (int i = 0; i < 10; i++) {
while (isWait) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + i + "个主线程--->" + Thread.currentThread().getName());
}
// 当主线程执行一次后,改变标识符,唤醒主子线程
isWait = true;
condition.signal();/类似this.notify()
}
lock.unlock();
}
}
public static void main(String[] args) {
ThreadSubMain threadSubMain = new ThreadSubMain();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
threadSubMain.subExcute(i);
}
}
}).start();
threadSubMain.mainExcute();
}
还没有评论,来说两句吧...