有三个线程,线程一只打印t1,线程二只打印t2,线程三只打印t3,输出到三个文件,第一个文件的打印顺序是t1 t2 t3 ...第二个是t2 t3 t1... 第三个是t3 t1 t2

有三个线程,线程一只打印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();
		
	}
}

打印结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值