编写两个线程,一个线程打印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();
}
}
}
}