有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC…
解题思路一:借鉴操作系统互斥的相关思想,设置了三个信号量来保证打印的顺序
但是这种方式非常麻烦,下面有参考别人的代码后,非常简洁的方法,可以直接跳到解题思路二!
public class TestMulti{
boolean printA; //true表示A已经打印,false表示尚未打印
boolean printB; //同理
boolean printC; //同理
public TestMulti(boolean printA,boolean printB,boolean printC){
this.printA=printA;
this.printB=printB;
this.printC=printC;
}
public synchronized void printA() throws InterruptedException{
while(!printC) //仔细思考为什么要用while?
wait();
System.out.print('A');
printA=true;
printC=false;
notifyAll();
}
public synchronized void printB() throws InterruptedException{
while(!printA)
wait();
System.out.print('B');
printB=true;
printA=false;
notifyAll();
}
public synchronized void printC() throws InterruptedException{
while(!printB)
wait();
System.out.print('C');
printC=true;
printB=false;
notifyAll();
}
public static void main(String[] args){
TestMulti test=new TestMulti(false,false,true); //保证A第一个打印
ThreadABC a=new ThreadABC(test);
ThreadABC b=new ThreadABC(test);
ThreadABC c=new ThreadABC(test);
a.setName("a");
b.setName("b");
c.setName("c");
a.start();
b.start();
c.start();
}
}
class ThreadABC extends Thread{
private TestMulti test;
public ThreadABC(TestMulti test){
this.test=test;
}
public void run(){
for(int i=0;i<10;i++)
try {
if(Thread.currentThread().getName().equals("a"))
test.printA();
else if(Thread.currentThread().getName().equals("b"))
test.printB();
else if(Thread.currentThread().getName().equals("c"))
test.printC();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
解题思路二:充分理解对象锁机制后,利用对象锁来同步解决问题就非常容易了,详细思路见下面代码。
//产生对象锁的类
class XunleiLock{
private String name="threadA";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Printer extends Thread{
private XunleiLock lock;
private String name;
private int count=10;
public Printer(String name,XunleiLock lock){ //为每一个线程配置一个锁
this.lock=lock;
this.name=name;
}
public void run(){
while(count>0){
synchronized(lock){ //同步代码块,保证每次只有一个线程能访问
if(lock.getName().equals(this.name)){
if(this.name.equals("threadA"))
{
System.out.print("A");
lock.setName("threadB"); //切换所对象,保证打印的顺序
}
else if(this.name.equals("threadB"))
{
System.out.print("B");
lock.setName("threadC");
}
else if(this.name.equals("threadC")){
System.out.print("C");
lock.setName("threadA");
}
count--;
}
}
}
}
}
public class TestABC2 {
public static void main(String[] args){
XunleiLock lock=new XunleiLock();
Printer A=new Printer("threadA",lock);
Printer B=new Printer("threadB",lock);
Printer C=new Printer("threadC",lock);
A.start();
B.start();
C.start();
}
}
仔细的分析上面的run方法,会发现虽然很方便的实现了顺序打印,但是每个线程需要不断的去判断自己是否获得了对象锁,想想有什么办法可以改进呢? 你想到了什么?对,就是使用wait()和notifyAll()......