12A34B56C….5152Z(超详细的讲解,都在代码里哦)

编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z。打印顺序为12A34B56C….5152Z。即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印,直到打印到整数52和字母Z结束

这是一道很经典的线程之间通信的问题,在做之前要想到做一个旗帜的类,来方便线程的释放和等待.这里我用到了一个flag类来进行标识,之后分别创了两个线程来释放或者等待CPU,要按顺序进行思考

以下就是一个boolean类型的flag类进行标志

// 一个用作标识的类
public class Flag {
	//自定义为flag为false
	private boolean flag;

	public Flag() {
		super();
		// TODO Auto-generated constructor stub
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}	
}

然后就是创建一个数字的线程子类来进行逻辑判断,代码如下

// 一个数字类
class NumToA extends Thread{
	//首先声明一个标志
	private Flag flag;
	//先定义好1-52的值的第一个
	static int a = 1;
	//写一个含有旗标的的构造器来初始化数字类
	public NumToA(Flag flag,String name) {
		super(name);
		this.flag = flag;
	}
	
	@Override
	public void run() {
	//run方法进来先准备好方法的临界条件
		while (a<=52) {
		//锁好进程,为了同步
			synchronized (flag) {
			//定义的flag为false,则跳过if判断,执行下面的打印语句
			if (flag.isFlag()){
				try {
					sleep(100);
					//如果flag为true的时候,就让该线程阻塞
					flag.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//分别打印1-52,这简单就不说了
			System.out.print(a);
			System.out.print(a+1);
			a+=2;
			//打印完之后,将flag的值转为true,再次执行循环就可进入if
			//然后if里面有wait,线程转为下一个
			flag.setFlag(true);
			//阻塞前打开其他的线程
			flag.notifyAll();
		}
		}
	}
}

以下是字母类的的代码,详解在代码里方便讲解

//字母类
class NumToB extends Thread{
	//老规矩,声明旗标
	private Flag flag;
	//这里就是整数转换为char类型,A为65
	static int b = 65;
	//和上面一样,初始化构造器和旗标
	public NumToB(Flag flag,String name) {
		super(name);
		this.flag = flag;
	}
	
	@Override
	public void run() {
		//声明临界条件
		while (b<=90) {
			//同步锁
			synchronized (flag) {
			//!的话,flag则为false的时候字母类进入阻塞状态
				if (!flag.isFlag()) {
					try {
						sleep(100);
						//阻塞进程,为了其他线程的加入
						flag.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//打印字母表
				System.out.print((char)b);
				b++;
				//将flag的值转为false,阻塞自己
				flag.setFlag(false);
				flag.notifyAll();
			}
		}
	}
}
通过这些代码就可以看出来,每次执行完自己的代码之后,就让自己进入阻塞状态,同时释放其他进程,让别人进行抢栈,即数字类执行一次之后,flag的值转换为true,阻塞自己数字类,然后字母类开始执行,执行一次之后,flag的值再次转换为false,阻塞自己的字母类,激活其他线程,之后数字类再次进行输出…
这样就逐条12A34B…5152Z就可以直接打印到控制台上去了.
//打印排列的类
public class Test {
	public static void main(String[] args) {
		Flag flag = new Flag();
		NumToA nt1 = new NumToA(flag, "数字");
		NumToB nt2 = new NumToB(flag, "字母");
		nt1.start();
		nt2.start();
	}
}

在这里插入图片描述

具体的实现类如下图所示(没有注释)

// An highlighted block
public class Test {
	public static void main(String[] args) {
		Flag flag = new Flag();
		NumToA nt1 = new NumToA(flag, "数字");
		NumToB nt2 = new NumToB(flag, "字母");
		nt1.start();
		nt2.start();
	}
}
class NumToA extends Thread{
	
	private Flag flag;
	static int a = 1;
	
	public NumToA(Flag flag,String name) {
		super(name);
		this.flag = flag;
	}
	
	@Override
	public void run() {
		while (a<=52) {
			synchronized (flag) {
			if (flag.isFlag()){
				try {
					sleep(100);
					flag.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.print(a);
			System.out.print(a+1);
			a+=2;
			flag.setFlag(true);
			flag.notifyAll();
		}
		}
	}
}
class NumToB extends Thread{
	private Flag flag;
	static int b = 65;
	public NumToB(Flag flag,String name) {
		super(name);
		this.flag = flag;
	}
	
	@Override
	public void run() {
		while (b<=90) {
			synchronized (flag) {
				if (!flag.isFlag()) {
					try {
						sleep(100);
						flag.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				System.out.print((char)b);
				b++;
				flag.setFlag(false);
				flag.notifyAll();
			}
		}
	}	
}

具体的实现就是这样,大家一起学习Java,一起快乐哦!!!(假装自己不会秃头O(∩_∩)O哈哈~)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现这个需求,我们可以利用两个通道来进行协程之间的同步。一个协程负责打印数字,另一个协程负责打印字母,然后通过通道来交替控制它们的执行顺序。以下是一个示例代码: ```go package main import ( "fmt" "sync" ) func printNumbers(chNum chan bool, chAlpha chan bool, wg *sync.WaitGroup) { defer wg.Done() for i := 1; i <= 52; i += 2 { <-chNum // 等待字母协程打印完毕 fmt.Printf("%d%d", i, i+1) chAlpha <- true // 通知字母协程可以开始打印 } } func printLetters(chNum chan bool, chAlpha chan bool, wg *sync.WaitGroup) { defer wg.Done() for i := 'A'; i <= 'Z'; i++ { <-chAlpha // 等待数字协程打印完毕 fmt.Printf("%c", i) chNum <- true // 通知数字协程可以开始打印 } } func main() { chNum := make(chan bool) // 数字协程通道 chAlpha := make(chan bool) // 字母协程通道 var wg sync.WaitGroup wg.Add(2) go printNumbers(chNum, chAlpha, &wg) go printLetters(chNum, chAlpha, &wg) chNum <- true // 通知数字协程可以开始打印 wg.Wait() fmt.Println() } ``` 在这个示例代码中,我们创建了两个通道`chNum`和`chAlpha`,分别用于数字协程和字母协程之间的同步。然后使用`sync.WaitGroup`来等待协程的完成。 通过交替地在协程之间发送和接收消息,我们可以实现数字和字母的交替输出。数字协程先打印1-52中的奇数,然后等待字母协程打印完毕后再继续打印下一个数字。字母协程负责打印A-Z,然后等待数字协程打印完毕后再继续打印下一个字母。 最终的输出结果将会按照1-52和A-Z的顺序交替打印,符合题目要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值