前些日子面试阿里,其中有一笔试题如下:
补充如下程序通过N个线程顺序循环打印从0至100,如给定N=3则输出:
thread0: 0
thread1: 1
thread2: 2
thread0: 3
thread1: 4
...
注意线程号与输出顺序间的关系。
当拿到题之后,内心分析:大概知道该题是要考试Java里线程之间协作相关的知识
当时是这样写的:
package com.zhoufy.example.thread.communication;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.StringUtils;
public class ThreadDemo {
private static int index = 1;
private static int endValue = 100;
private static AtomicInteger count = new AtomicInteger(0);
private static ExecutorService executor = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
boolean isLoop = true;
while (isLoop) {
if (count.get() > endValue) {
isLoop = false;
break;
}
executor.execute(new Runnable() {
@Override
public void run() {
try {
if (count.get() > endValue) {
return;
}
String name = Thread.currentThread().getName();
int j = Integer.parseInt(StringUtils.substring(name, name.length() - 1, name.length()));
if (j == index) {
System.out.println("线程(" + Thread.currentThread().getName() + ")" + (count.getAndIncrement()));
if (index == 3) {
index = 1;
} else {
index++;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
executor.shutdown();
}
}
因为有时间的限制,所以写完测试了一下,就提交了,并没有进行优化,只是实现了题目的要求,其实自己并不满意!
事后还是想通过Java的wait、notify来实现的,所以自己又优化了一下:
package com.zhoufy.example.thread.communication;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线程通信
*
* @author zhoufy
* @date 2019年1月22日 下午5:35:51
*/
public class ThreadCommunicationTest3 {
private volatile AtomicInteger index = new AtomicInteger(1);
public static void main(String[] args) {
ThreadCommunicationTest3 t = new ThreadCommunicationTest3();
t.test();
}
private void test(){
Print m = new Print();
new Thread1(m);
new Thread2(m);
new Thread3(m);
}
class Print{
public synchronized void print(int remainder){
if(index.get()%3==remainder){
System.out.println(Thread.currentThread().getName()+":"+(index.get()-1));
index.incrementAndGet();
notifyAll();
}
if(index.get()<100){ //如果不加这一句,最后会有一个线程挂起
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Thread1 implements Runnable {
Print m;
public Thread1(Print m1) {
this.m = m1;
new Thread(this, "Thread0").start();
}
public void run() {
while(true){
if(index.get()>100){
break;
}
m.print(1);
}
}
}
class Thread2 implements Runnable {
Print m;
public Thread2(Print m2) {
this.m = m2;
new Thread(this, "Thread1").start();
}
public void run() {
while(true){
if(index.get()>100){
break;
}
m.print(2);
}
}
}
class Thread3 implements Runnable {
Print m;
public Thread3(Print m3) {
this.m = m3;
new Thread(this, "Thread2").start();
}
public void run() {
while(true){
if(index.get()>100){
break;
}
m.print(0);
}
}
}
}