写了一个多线程的打印,如一个线程打印12345,另一个线程打印ABCDE,最后结果是1A2B3C4D5E。
以下是代码及部分测试结果:
打印客户端类:PrinterCilent
package com.syz.thread.print;
public class PrinterCilent {
public static void main(String[] args) {
String s1 = "1234567890";
String s2 = "abcdefghij";
String s3 = "ABCDEFGHIJ";
Printer p = new Printer();
Thread t1 = new PrinterThread(p, s1);
Thread t2 = new PrinterThread(p, s2);
Thread t3 = new PrinterThread(p, s3);
t1.start();
t2.start();
t3.start();
}
}
真正负责打印字符的类:Printer
package com.syz.thread.print;
public class Printer {
private PrinterState who;// 打印谁,由打印状态决定
public void setFirst(PrinterState state) {
this.who = state;
}
/**
* 打印,如果传过来的状态与要打印的状态一样,则打印,并设置要打印的状态为其它线程的状态;否则线程等待。
* @Title: print
* @Description: TODO
* @param c 要打印的字符
* @param state 当前状态
* @param status 是否是最后一个要打印的字符,判定某批要打印字符串的结束标志
* @return: void
*/
public synchronized void print(char c, PrinterState state, int status) {
while (who != state) {
try {
this.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(c);
turn(state);
if (status != 0) {
state.setIdle(true);
}
this.notifyAll();
}
private void turn(PrinterState state) {
PrinterState cur = state;
if (!cur.getNext().isIdle()) {
who = cur.getNext();
}
else {
cur = state.getNext();
turn(cur);
}
}
}
打印线程类:PrinterThread
package com.syz.thread.print;
import java.util.LinkedList;
import java.util.List;
public class PrinterThread extends Thread {
private String s;
private Printer p;
private PrinterState state;
private static List<PrinterState> spool = new LinkedList<>();
private List<PrinterState> pool = spool;
public PrinterThread(Printer p, String s) {
if (s == null || "".equals(s)) {
throw new RuntimeException(getName() + "\t所有打印的字符串不能为空!");
}
this.p = p;
this.s = s;
PrinterState state = new PrinterState();
pool.add(state);
freshPool();
this.state = pool.get(pool.size() - 1);
this.p.setFirst(pool.get(0));
}
/**
* 重新给打印状态赋值,主要是指定当前状态的下个状态
* @Title: freshPool
* @Description: TODO
* @return: void
*/
private void freshPool() {
if (pool.size() > 0) {
for (int i = 0; i < pool.size(); i++) {
PrinterState p1 = pool.get(i);
PrinterState p2 = null;
if (i == pool.size() - 1) {
p2 = pool.get(0);
}
else {
p2 = pool.get(i + 1);
}
p1.setNext(p2);
}
}
}
public void run() {
char[] ary = s.toCharArray();
int len = ary.length;
for (int i = 0; i < len; i++) {
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
if (i == len - 1) {
p.print(ary[i], state, 1);
}
else {
p.print(ary[i], state, 0);
}
}
}
}
测试用例1:
String s1 = "1234567890";
String s2 = "abcdefghij";
String s3 = "ABCDEFGHIJ";
启三个线程传入s1,s2,s3
结果1:
1aA2bB3cC4dD5eE6fF7gG8hH9iI0jJ
测试用例2:
String s4 = "1357";
String s5 = "2468";
启两个线程传入s4,s5
结果2:
12345678
测试用例3:
String s1 = "1234567890";
String s2 = "abc";
String s3 = "ABCDEFG";
启三个线程传入s1,s2,s3
结果3:
1aA2bB3cC4D5E6F7G890
最后说明:
本例中有个缺陷。如果要打印三个字符串,必须new三个线程,并且三个都要start。假设我new了三个线程,但只启动了两个,会发生线程一直等待现象,没有线程去改变状态。
如果有人能解决这个问题,请留言告诉我啊,谢谢了。