多线程按序执行
笔试遇到的题目,涉及到多线程,题目大意是有三个线程,分别名为ABC,要求这三线程按序执行十遍打印,打印结果如:ABCABCABC…ABC。
我的思路是将ABC看作一个操作,然后执行10遍。
一开始想的很简单,直接使用循环,然后ExecutorService.exture顺序执行。
public static void print4ID(){
Object obj = new Object();
for(int i=0; i<10; i++){
synchronized(obj){
ExecutorService e = Executors.newFixedThreadPool(3);
e.execute(getThread("A"));
e.execute(getThread("B"));
e.execute(getThread("C"));
e.shutdown();
}
}
}
public static Thread getThread(String uid){
return new Thread(uid){
public void run(){
System.out.print(this.getName());
}
};
}
这样的结果是乱序的
ABCABCABCABCABCABCABCBCABCABCA
查了资料后,发现较好的方法是使用synchronized和ArrayList,或者是使用Thread.join()管理三个线程,打印ABC,然后在使用ScheduledExecutorService.scheduleAtFixedRate执行10遍。
1.Thread.join()
//使用Thread.join(),顺序打印ABC
public void print1() throws InterruptedException {
Thread t1 = new Thread(
() -> System.out.print(Thread.currentThread().getName())
,"A");
Thread t2 = new Thread(
() -> System.out.print(Thread.currentThread().getName())
,"B");
Thread t3 = new Thread(
() -> System.out.print(Thread.currentThread().getName())
,"C");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
}
public void print4ID3(){
AtomicInteger i = new AtomicInteger(1);
ScheduledExecutorService e = Executors.newScheduledThreadPool(10);
e.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
try {
print();
if(i.getAndIncrement() == 10)
e.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 1, 1, TimeUnit.SECONDS);
System.out.println();
}
2.synchronized和ArrayList
//ArrayList顺序保存线程ABC,然后synchronized控制线程打印
public void print4ID4(){
ArrayList<Runnable> rs = new ArrayList<Runnable>(3);
rs.add(getThread("A"));
rs.add(getThread("B"));
rs.add(getThread("C"));
AtomicInteger i = new AtomicInteger(1);
ScheduledExecutorService e = Executors.newScheduledThreadPool(10);
e.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
runThread(rs);
if(i.getAndIncrement() == 10)
e.shutdown();
}
}, 1, 1, TimeUnit.SECONDS);
}
public void runThread(ArrayList<Runnable> rs){
for(Runnable r:rs){
synchronized(this){
r.run();
}
}
}