使用Java线程并发库实现两个线程交替打印的线程题

时间:2021-12-15 05:55:57

背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题。晚上闲着没事就决定把它实现出来。

题目:

1.开启两个线程,一个线程打印A~Z,两一个线程打印1~52的数据。

2.实现交替打印,输出结果为12A34B...........5152Z.

3.请用多线程方式实现。

这种只有两个线程交替打印数据的题目其实相对还是比较简单的,如果利用传统线程无非就是synchronized(线程互斥)与wait(),notify()的问题。

今天不用传统线程解决这个问题,我们用Java 1.5提供的线程并发库中的类来实现这个功能(实现流程和传统线程一样)

下面是实现代码(我都加了注释,如果还是不同大家可以查看Java 1.5以上的帮助文档)

package cn.yw.thread.practice;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* 多线程练习:
* 1.开启一个线程打印1~52,开启另一个线程打印A~Z
* 打印方式:12A34B46C依次打印
* @author yw-tony
*
*/
public class PracticeTest { public static void main(String[] args){
final DataPrint data = new DataPrint();
//打印字母的线程(大家也可以把这两个线程抽取出来作为两个单独的类,这里为了实现简单我就直接写在main方法中了)
new Thread(new Runnable(){
@Override
public void run() {
while(data.letterFlag){
data.printLetter();
}
}
}).start(); //打印数字的线程
new Thread(new Runnable(){
@Override
public void run() {
while(data.numFlag){
data.printNun();
}
}
}).start(); }
/**
* 打印类
* @author yw-tony
*
*/
static class DataPrint{
public boolean letterFlag = true;//线程结束标记;
public boolean numFlag = true;
//数字的初始值
int num = 1;
//字母的初始值
//这里A~Z的字母对应的阿拉伯数字为65~90,
int letter = 65;
//线程等待标记
boolean flag = true;
//java线程并发库中的锁相当与(synchronized)
Lock lock = new ReentrantLock();
//线程并发库中用于线程之间通讯的类相当于wait(),notify()
Condition condLetter = lock.newCondition();
Condition condNum = lock.newCondition();
/**
* 打印字字母的方法
*
*/
public void printLetter(){
//如果打印到Z则结束线程并停止
if(letter >= 90 ){
letterFlag = false;
return ;
}
//锁定代码块,锁定时其他线程不能访问其中内容
lock.lock();
try{
if(flag){//如果执行打印数字的线程正在执行,则该线程进入等待状态
condLetter.await();
}
System.out.println(Thread.currentThread().getName()+":"+(char)letter);
letter++;
Thread.sleep(100);
//打印执行完成,唤醒打印数字的线程
flag = true;
condNum.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
//解锁当前代码快
lock.unlock();
} }
/**
* 打印数字的方法
*/
public void printNun(){
//如果打印到52则结束线程并停止
if(num>=52){
numFlag = false;
return;
}
lock.lock();
try{
if(!flag){
condNum.await();
}
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
System.out.println(Thread.currentThread().getName()+":"+num);
num++;
Thread.sleep(100);
flag = false;
condLetter.signal();//唤醒打印字母的线程
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
}