最近一直在公司对使用storm来统计相关数据时,发现需要使用到高并发的知识,基于之前对高并发相关知识没有系统的学习,现在慢慢研究和学习。
在解决两个线程相互交替执行任务时,我们用到了重入锁ReentrantLock,又叫做递归锁。重入锁指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响,其实ReentrantLock和synchronized都是可重入锁。
public boolean letterFlag = true;//线程结束标记;
public boolean numFlag = true;
//数字的初始值
int num = 1;
//字母的初始值
//这里A~Z的字母对应的阿拉伯数字为65~90,
int letter = 65;
//线程等待标记
boolean flag = true;
Lock lock = new ReentrantLock();
//线程并发库中用于线程之间通讯的类相当于wait(),notify()
Condition condLetter = lock.newCondition();
Condition condNum = lock.newCondition();
public void printLetter(){
//如果打印到Z则结束线程并停止
if(letter >= 90 ){
letterFlag = false;
return ;
}
//锁定代码块,锁定时其他线程不能访问其中内容
lock.lock();
try{
if(flag){//如果执行打印数字的线程正在执行,则该线程进入等待状态
condLetter.await();
}
System.out.println(Thread.currentThread().getName()+":"+(char)letter);
letter++;
Thread.sleep(100);
//打印执行完成,唤醒打印数字的线程
flag = true;
condNum.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
//解锁当前代码快
lock.unlock();
}
}
public void printNun(){
//如果打印到52则结束线程并停止
if(num>=52){
numFlag = false;
return;
}
lock.lock();
try{
if(!flag){
condNum.await();
}
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
Thread.sleep(100);
flag = false;
condLetter.signal();//唤醒打印字母的线程
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
我们可以看到使用flag进行状态变化的标识,以及用到了锁的工作:
Condition condLetter = lock.newCondition();
Condition condNum = lock.newCondition();
上面两个锁对象就是针对写字母和写数字模块的控制写入顺序,这样就会就可以产生交替变换写数据
网友评论