启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20....
1 传统锁synchronized实现
启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20…依次类推, 直到打印到60。
提示:定义一个同步方法,在方法中使用循环的方式输出连续的5个数字,方法执行前,可以通过标记的方式判断是否是当前线程应该执行,如果是,则执行输出逻辑,如果不是,则wait进入等待队列,在方法执行结束前,必须使用notifyAll唤醒其他所有线程。
public class Problem02 {
public static void main(String[] args) {
final Hander hander = new Hander();//实例化Hander对象
//循环建立三个线程.并启动
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<5;j++) {
hander.print(Thread.currentThread().getName());
}
}
}, i + "").start();
}
}
}
class Hander {
//打印的数字 变量
private int no = 1;
//判断变量
private int status = 0;
// 将该方法上锁
public synchronized void print(String threadName) {
int threadIndex = Integer.parseInt(threadName);//将threadName转换为int
//不相等则进入等待
while (threadIndex != status) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("Thread-"+threadName+" : ");//输出线程名
//打印数字循环
for (int count = 0; count < 5; count++, no++) {
if (count > 0) {
System.out.print(",");
}
System.out.print(no);
}
System.out.println();
status = (status + 1) % 3;//改变status的值
this.notifyAll();//唤醒其他线程
}
}
2 lock可重入锁实现 (以下内容有毒,慎重阅读,我居然写完了,我的天,佩服自己三秒钟!!! )
启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5 然后是线程2打印6,7,8,9,10 然后是线程3打印11,12,13,14,15.接着再由线程1打印16,17,18,19,20…依次类推, 直到打印到60。
提示:定义一个类,其中定义三个方法,分别用于打印符合要求的数字。定义三个condition条件,通过线程编号来判断应该是哪一个线程执行输出逻辑,哪一个线程应该执行await等待逻辑。注意,一定要在finally中unlock释放锁,且在释放锁之前要使用condition的signalAll唤醒其他等待线程。
public class T {
int num = 0;
int index = 0;
Lock lock = new ReentrantLock(true);
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
void m1(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c1.await();
}
System.out.print(Thread.currentThread().getName() + " - " + index + " : ");
for(int i = 1; i <= 5; i++){
System.out.print(++num + ",");
}
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c2.signalAll();
c3.signalAll();
lock.unlock();
}
}
void m2(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c2.await();
}
System.out.print(Thread.currentThread().getName() + " - " + index + " : ");
for(int i = 1; i <= 5; i++){
System.out.print(++num + ",");
}
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c1.signalAll();
c3.signalAll();
lock.unlock();
}
}
void m3(){
int threadIndex = Integer.parseInt(Thread.currentThread().getName());
try{
lock.lock();
while(threadIndex != index){
c3.await();
}
System.out.print(Thread.currentThread().getName() + " - " + index + " : ");
for(int i = 1; i <= 5; i++){
System.out.print(++num + ",");
}
System.out.println();
}catch(Exception e){
e.printStackTrace();
}finally{
index = (index + 1) % 3;
c2.signalAll();
c1.signalAll();
lock.unlock();
}
}
public static void main(String[] args) {
final T t = new T();
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<4;j++) {
t.m1();
}
}
}, "0").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<4;j++) {
t.m2();
}
}
}, "1").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int j=0;j<4;j++) {
t.m3();
}
}
}, "2").start();
}
}