Java多线程题目一道

三个线程交替打印antantant…,一个打印a,一个打印n,一个打印t(编程语言自选)

Java实现,方法一,通过两把锁来控制打印,思路如下:

ThreadA,ThreadN,ThreadT分别会打印a,n,t,定义三把锁LockA,LockN,LockT作为对应打印线程必须要获取的锁,除此之外每个线程打印对应字母有序,也就是每个字母前面的字母是对应的,比如现在想打印n,那么前面必须已经打印了a,那么ThreadA自身的LockA必须释放掉了才能确认a已经打印了,然后ThreadN获取了LockA,然后申请到LockN,打印n,接着notify唤醒所有阻塞等待LockN的线程,其实只有ThreadT,然后释放掉LockN,再wait立即释放掉LockA,最后ThreadN进入wait状态,如此轮回;如果最后不wait一下,那么ThreadN将会和后ThreadT线程进行锁LockN的竞争,如果又抢到了,那么又会打印一个N

画一个简单的图理解

而一开始ant的顺序,就在初始化的时候通过Thread.sleep来控制,源代码

package Love;

/**
* Hello world!
*
*/

public class App {

public static class ThreeThreads implements Runnable {
private String word;
private Object frontLock;
private Object selfLock;

private ThreeThreads(String word, Object frontLock, Object selfLock) {
this.word = word;
this.frontLock = frontLock;
this.selfLock = selfLock;
}
// a LockT LockA
// n LockA LockN
// t LockN LockT
@Override
public void run() {
while (true) {
synchronized (frontLock) {
synchronized (selfLock) {
System.out.print(word);
selfLock.notifyAll();
}
try {
frontLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

public static void main(String[] args) throws InterruptedException {
Object LockA = new Object();
Object LockN = new Object();
Object LockT = new Object();

ThreeThreads A = new ThreeThreads("a", LockT, LockA);
ThreeThreads N = new ThreeThreads("n", LockA, LockN);
ThreeThreads T = new ThreeThreads("t", LockN, LockT);

new Thread(A).start();
Thread.sleep(1000);
new Thread(N).start();
Thread.sleep(1000);
new Thread(T).start();
Thread.sleep(1000);
}
}

 

Java实现,方法二,如果觉得上面加锁比较绕,可以考虑通过变量来控制顺序,最关键还是保持ant顺序,这里可以定义一个static变量,整体思路:

flag=0,word=a,执行ThreadA打印a,flag++

flag=1,word=n,执行ThreadN打印n,flag++

flag=2,word=t,执行ThreadT打印t,flag++

flag=3,word=a,执行ThreadA打印a,flag++

……

最关键步骤是分支结构里flag%3的结果和word一起决定Thread的执行或者说字母的打印,然后012分别对应ant即可

源码如下:

package Love;

/**
* Hello world!
*/

public class App {

public static class ThreeThreads implements Runnable {

private static int flag = 0;
private final String A = "a";
private final String N = "n";
private final String T = "t";
private String word;

private ThreeThreads(String word) {
this.word = word;
}

@Override
public void run() {
while (true) {
switch (flag % 3) {
case 0:
if (A.equals(word)) {
System.out.print(word);
flag++;
}
break;
case 1:
if (N.equals(word)) {
System.out.print(word);
flag++;
}
break;
case 2:
if (T.equals(word)) {
System.out.print(word);
flag++;
}
break;
default:
System.out.println("flag error");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}
public static void main(String[] args) {
ThreeThreads A = new ThreeThreads("a");
ThreeThreads N = new ThreeThreads("n");
ThreeThreads T = new ThreeThreads("t");

new Thread(A).start();
new Thread(N).start();
new Thread(T).start();
}
}

 

Java实现,方法三,上面要么锁控制,要么变量控制,还可以只用一把锁和一个静态变量flag=0来控制打印,具体思路:

比如ThreadA,now=0,next=1,synchronized锁住,判断while当now!=flag,立即释放锁,并休眠,这里主要是为了保持顺序,不应该此刻打印的都休眠,如果now=flag,打印a,并且flag=next,这样flag的值就是ThreadN的now,下一个判断就决定了ThreadA,ThreadN,ThreadT这个顺序,最后需要notifyAll所有线程,开始锁的争夺,可参考下面的简单图

源码如下

package Love;

/**
* Hello world!
*/

public class App {

public static class ThreeThreads implements Runnable {

private String word;
private Object lock;
private final int next;
private final int now;
private static int flag = 0;

private ThreeThreads(Object lock, int now, int next, String word) {
this.lock = lock;
this.word = word;
this.next = next;
this.now = now;
}

@Override
public void run() {
while (true) {
synchronized (lock) {
while (flag != now) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(word);
flag = next;
lock.notifyAll();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

}

public static void main(String[] args) throws InterruptedException {
Object Lock = new Object();

ThreeThreads A = new ThreeThreads(Lock, 0, 1, "a");
ThreeThreads N = new ThreeThreads(Lock, 1, 2, "n");
ThreeThreads T = new ThreeThreads(Lock, 2, 0, "t");

new Thread(A).start();
Thread.sleep(1000);
new Thread(N).start();
Thread.sleep(1000);
new Thread(T).start();
Thread.sleep(1000);
}
}

 

还有ReentrantLock以及Condition对象的加锁方式还没用熟,基础才是王道……

发表评论