Java多线程顺序打印abc的多种写法
问题描述:
有三个线程顺序打印abc十次,请用线程同步实现。
问题分析:
这个问题是一个线程同步的问题,一共打印十轮每一轮都要保证a,b,c三个线程顺序执行。本文给出以下几个常用方法。
CAS实现
package com.shu.yzy.thread;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 三个线程按次序轮流打印a,b,c AtomicInteger 实现
* @author yzy
*/
public class ThreadDemo implements Runnable{
private static AtomicInteger currentCount = new AtomicInteger(0);
private static final Integer MAX_COUNT = 30;
private static String [] chars = {"a", "b", "c"};
private String name;
public ThreadDemo(String name) {
this.name = name;
}
@Override
public void run() {
while(currentCount.get()<MAX_COUNT){
if(this.name.equals(chars[currentCount.get()%3])){
printAndPlusOne(this.name + "\t" + currentCount);
}
}
}
public void printAndPlusOne(String content){
System.out.println(content);
currentCount.getAndIncrement();
}
public static void main(String [] args){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 20, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.execute(new ThreadDemo("a"));
threadPoolExecutor.execute(new ThreadDemo("b"));
threadPoolExecutor.execute(new ThreadDemo("c"));
threadPoolExecutor.shutdown();
}
}
synchronized实现
package com.shu.yzy.thread;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 三个线程按次序轮流打印a,b,c synchronized + wait() + notifyAll() 实现
* Integer 对象不能作为synchronized锁的对象,因为修改Integer对象的值会改变对象引用
* @author yzy
*/
public class ThreadDemo2 implements Runnable {
private static String[] chars = {"a", "b", "c"};
private static final OperateInteger operateInteger = new OperateInteger(0, 30);
private String name;
public ThreadDemo2(String name) {
this.name = name;
}
@Override
public void run() {
while (operateInteger.getCurrentCount() < operateInteger.getMaxCount()) {
synchronized (operateInteger) {
if (operateInteger.getCurrentCount() < operateInteger.getMaxCount()) {
if (this.name.equals(chars[operateInteger.getCurrentCount() % 3])) {
operateInteger.printAndPlusOne();
operateInteger.notifyAll();
} else {
try {
operateInteger.wait();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
}
}
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 20, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.execute(new ThreadDemo2("a"));
threadPoolExecutor.execute(new ThreadDemo2("b"));
threadPoolExecutor.execute(new ThreadDemo2("c"));
threadPoolExecutor.shutdown();
}
private static class OperateInteger{
private int currentCount;
private int maxCount;
private void printAndPlusOne() {
System.out.println(chars[currentCount%3] + "\t" + currentCount);
currentCount++;
}
public OperateInteger(int currentCount, int maxCount) {
this.currentCount = currentCount;
this.maxCount = maxCount;
}
public int getCurrentCount() {
return currentCount;
}
public int getMaxCount() {
return maxCount;
}
}
}
Lock实现
package com.shu.yzy.thread;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 三个线程按次序轮流打印a,b,c Lock实现
* @author yzy
*/
public class ThreadDemo3 implements Runnable{
private static Lock lock = new ReentrantLock();
private static Integer currentCount = 0;
private static final Integer MAX_COUNT = 30;
private static String [] chars = {"a", "b", "c"};
private String name;
public ThreadDemo3(String name) {
this.name = name;
}
@Override
public void run() {
while(currentCount<MAX_COUNT){
//lock() 与 unlock() 必须和 try...finally 配套使用 避免出现异常不解锁
try{
lock.lock();
while(this.name.equals(chars[currentCount%3])&¤tCount<MAX_COUNT){
printAndPlusOne(this.name);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public void printAndPlusOne(String name){
System.out.println(name + "\t" + currentCount);
currentCount ++;
}
public static void main(String [] args){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 20, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.execute(new ThreadDemo3("a"));
threadPoolExecutor.execute(new ThreadDemo3("b"));
threadPoolExecutor.execute(new ThreadDemo3("c"));
threadPoolExecutor.shutdown();
}
}
JUC 包同步工具实现(以CylicBarrier为例)
package com.shu.yzy.thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadDemo4 implements Runnable{
private static CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
private static Integer currentCount = 0;
private static final Integer MAX_COUNT = 30;
private static String [] chars = {"a", "b", "c"};
private String name;
public ThreadDemo4(String name) {
this.name = name;
}
@Override
public void run() {
while(currentCount<MAX_COUNT){
while(this.name.equals(chars[currentCount%3]))
printAndPlusOne(this.name + "\t" + currentCount);
try {
cyclicBarrier.await();
}catch (Exception e){
e.printStackTrace();
}
}
}
public void printAndPlusOne(String name){
System.out.println(name);
currentCount ++;
}
public static void main(String [] args){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 3, 20, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
threadPoolExecutor.execute(new ThreadDemo4("a"));
threadPoolExecutor.execute(new ThreadDemo4("b"));
threadPoolExecutor.execute(new ThreadDemo4("c"));
threadPoolExecutor.shutdown();
}
}