有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件,第一个文件的打印顺序是t1 t2 t3 …第二个是t2 t3 t1 … 第三个是t3 t1 t2…循环打印
听说这个题很多大厂面试都有出过
分析: 保证顺序执行则3个线程都是循序执行的T1T2T3T1T2T3T1T2T3…这样顺序执行,
则要么用wait(),notify(),notifyAll(),
要么用condition的await(),signal(),signalAll()
程序启动:
count=0: T1先执行, 第一次执行 线程T1只打印文件1中t1的值, 执行完,唤醒T2, T1等待,并释放锁, 这一步的关键是判断T1第一次执行时只打印文件1, 下一次T1执行的时候所有文件都打印t1,看图就是count=3的时候T1执行,所有文件都打印
count=1: T2执行, 第一次执行 线程T2只打印文件1和文件2中的t2, 执行完唤醒T3, T2等待, 后续执行T2的时候所有文件都打印t2
count=2 : T3执行, 第一次执行就打印所有文件的t3, 看图, 执行完,怎么办,当然是唤醒其他线程, 根据count取模的值判断该哪个线程执行
怎么说呢, 这其实就是一个线程交替执行的题目
分析完成,代码如下
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
/**
* 次数标识,用来区分哪个线程打印
*/
private static volatile int count = 0;
private static Lock lock = new ReentrantLock();
private static Condition thread1 = lock.newCondition();
private static Condition thread2 = lock.newCondition();
private static Condition thread3 = lock.newCondition();
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception{
PrintWriter pw1 = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
"C:/Users/Administrator/Desktop/test1.txt",true),"utf-8")));
PrintWriter pw2 = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
"C:/Users/Administrator/Desktop/test2.txt",true),"utf-8")));
PrintWriter pw3 = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
"C:/Users/Administrator/Desktop/test3.txt",true),"utf-8")));
new Thread(()->{
lock.lock();
try {
while(true) {
if(count%3== 0) { //线程t1进行打印的标志
pw1.print("t1"); //文件1必打印t1
pw1.flush();
if(count != 0) { //保证T1线程执行第一次的时候不其他两个文件不打印
pw2.print("t1,");
pw3.print("t1");
pw2.flush();
pw3.flush();
}
System.out.println("T1执行时 count="+count);
count++;
thread2.signal();
}else {
thread1.await();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();//释放锁
}
}).start();
new Thread(()->{
lock.lock();
try {
while(true) {
if(count%3 == 1) {//T2线程执行的时候文件1和文件2都会打印t2, 只有T2第一次的时候文件3不打印
pw1.print("t2");
pw2.print("t2");
pw1.flush();
pw2.flush();
if(count > 1) { //保证第一次执行线程t2时,文件3不打印
pw3.print("t2,");
pw3.flush();
}
System.out.println("T2执行时 count="+count);
count++;
thread3.signal();
}else {
thread2.await();
}
}
} catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}).start();
new Thread(()->{
lock.lock();
try {
while(true) {
if(count%3 == 2) { //等到线程T3执行的时候3个文件都会打印
pw1.print("t3,");
pw2.print("t3");
pw3.print("t3");
pw1.flush();
pw2.flush();
pw3.flush();
System.out.println("T3执行时 count="+count);
count++;
thread1.signalAll(); //同时唤醒所有线程
}else {
thread3.await();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}).start();
}
}
控制台输出: 线程循环交替执行
题2:
有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环这3中操作
/**
* 有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,在控制台上输出t1 t2 t3 。。循环5遍
* 之后输出t2 t3 t1。。5遍 再输出t3 t1 t2。。5遍之后就循环
* @author Administrator
* 解题思路: 线程T1T2T3, 顺序执行5遍之后,改变线程执行顺序为T2T3T1执行5遍,再改变顺序执行T3T1T2线程执行5遍,然后在回到原来的顺序,如此循环
*/
public class test2 {
static int count = 0;
static Object lock = new Object();
//初始线程顺序位标识
static int a = 0;
static int b = 1;
static int c = 2;
public static void main(String[] args) {
new Thread(()->{
synchronized (lock) {
while(true){
try {
if(count%3 == a) {
System.out.print("t1");
count++;
if(count%15 == 0) { //改变线程执行顺序
a = (a+2)%3;//1
b = (b+2)%3;//2
c = (c+2)%3;//0
System.out.println(",输出5次t2t3t1完毕,改变线程执行顺序位a="+a+",b="+b+",c="+c);
Thread.sleep(500L);
}
lock.notifyAll();
}else {
lock.wait();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(()->{
synchronized (lock) {
while(true){
try {
if(count%3 == b) {
System.out.print("t2");
count++;
if(count%15 == 0) { //改变线程执行顺序
a = (a+2)%3;//0
b = (b+2)%3;//1
c = (c+2)%3;//2
System.out.println(",输出5次t3t1t2完毕,改变线程执行顺序位a="+a+",b="+b+",c="+c);
Thread.sleep(500L);
}
lock.notifyAll();
}else {
lock.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(()->{
synchronized (lock) {
while(true){
try {
if(count%3 == c) {
System.out.print("t3");
count++;
if(count%15 == 0) { //改变线程执行顺序
a = (a+2)%3;//2
b = (b+2)%3;//0
c = (c+2)%3;//1
System.out.println(",输出5次t1t2t3完毕,改变线程执行顺序位a="+a+",b="+b+",c="+c);
Thread.sleep(500L);
}
lock.notifyAll();
}else {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
打印结果: