多线程之间是抢占资源的,使用线程通信可以达到线程按序执行的目的
线程共享资源类, 首先创建一个资源类, 包含三个打印的方法以及首次打印的字符串
多个线程访问,方法加synchronized同步锁
class Resource {
String currentPrint = "AA"; // 初始打印,打印之后赋值为下一个要打印的内容
/**
* 打印AA
* @param next 下一个要打印的字符串
* @throws InterruptedException
*/
public synchronized void printAA(String next) throws InterruptedException {
// 不是要打印的内容, 阻塞线程
while (!Objects.equals(currentPrint, "AA")) {
wait();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + ": AA");
}
currentPrint= next;
// 随机唤醒一个线程
notify();
}
/**
* 打印BB
* @param next 下一个要打印的字符串
* @throws InterruptedException
*/
public synchronized void printBB(String next) throws InterruptedException {
// 不是要打印的内容, 阻塞线程
while (!Objects.equals(currentPrint, "BB")) {
wait();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + ": BB");
}
currentPrint= next;
// 随机唤醒一个线程
notify();
}
/**
* 打印CC
* @throws InterruptedException
*/
public synchronized void printCC() throws InterruptedException {
// 不是要打印的内容, 阻塞线程
while (!Objects.equals(currentPrint, "CC")) {
wait();
}
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + ": CC");
}
}
}
创建线程执行程序进行交替打印
public class AABBCC {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = null;
try {
// 创建一个最大长度为3的线程池
threadPoolExecutor = new ThreadPoolExecutor(3, 3, 0,
TimeUnit.SECONDS, new LinkedBlockingDeque(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
Resource resource = new Resource();
// 将要执行的任务插入到集合中
List list = new ArrayList<>();
list.add(()->{try { resource.printAA("BB"); } catch (InterruptedException e) { e.printStackTrace(); }});
list.add(()->{try { resource.printBB("CC"); } catch (InterruptedException e) { e.printStackTrace(); }});
list.add(()->{try { resource.printCC();} catch (InterruptedException e) {e.printStackTrace();}});
for (int i = 0; i < list.size(); i++) {
threadPoolExecutor.execute(list.get(i));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭线程池
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
}
}
}
}
/**
* 打印字符串
* @param currentPrintParam 当前
* @param next 下一个
* @param times 打印次数
* @throws InterruptedException
*/
public synchronized void printStr(String currentPrintParam,String next, int times) throws InterruptedException {
// 不是要打印的内容, 阻塞线程
while (!Objects.equals(currentPrint, currentPrintParam)) {
wait();
}
for (int i = 0; i < times; i++) {
System.out.println(Thread.currentThread().getName() + ": "+ currentPrint);
}
currentPrint = next;
// 随机唤醒一个线程
notify();
}
调用方法替换
Resource resource = new Resource();
// 将要执行的任务插入到集合中
List list = new ArrayList<>();
list.add(()->{try { resource.printStr("AA", "BB", 3); } catch (InterruptedException e) { e.printStackTrace(); }});
list.add(()->{try { resource.printStr("BB", "CC", 3); } catch (InterruptedException e) { e.printStackTrace(); }});
list.add(()->{try { resource.printStr("CC", "", 3);} catch (InterruptedException e) {e.printStackTrace();}});
for (int i = 0; i < list.size(); i++) {
threadPoolExecutor.execute(list.get(i));
}
执行结果
JDK5在java.util.concurrent包下提供了Lock并发锁
资源类代码新增
Lock lock = new ReentrantLock(); // 并发锁
Condition aCondition = lock.newCondition();
Condition bCondition = lock.newCondition();
Condition cCondition = lock.newCondition();
/**
* 打印字符串
* @param currentPrintParam 当前线程打印
* @param nextPrint 下一个线程打印
* @param currentCondition 当前线程
* @param nextCondition 下一个线程
* @param times 打印次数
* @throws InterruptedException
*/
public void lockPrintStr(String currentPrintParam, String nextPrint, Condition currentCondition, Condition nextCondition, int times) {
lock.lock();
try {
// 不是要打印的内容 阻塞线程
while (!Objects.equals(currentPrint, currentPrintParam)) {
currentCondition.await();
}
for (int i = 0; i < times; i++) {
System.out.println(Thread.currentThread().getName() + ": "+ currentPrint);
}
currentPrint = nextPrint;
// 唤醒下一个线程
if (!Objects.isNull(nextCondition)) {
nextCondition.signal();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放锁
if (lock != null) {
lock.unlock();
}
}
}
调用新增的方法
Resource resource = new Resource();
// 将要执行的任务插入到集合中
List list = new ArrayList<>();
list.add(()->{resource.lockPrintStr("AA", "BB", resource.aCondition, resource.bCondition, 3);});
list.add(()->{resource.lockPrintStr("BB", "CC", resource.bCondition, resource.cCondition, 3);});
list.add(()->{resource.lockPrintStr("CC", "", resource.cCondition, null, 3);});
for (int i = 0; i < list.size(); i++) {
threadPoolExecutor.execute(list.get(i));
}
执行结果
多次执行的结果中可以看出,由三个线程交替打印AABBCC