方法1:使用boolean标记
package com.ziyear.exam;
/**
* 3个线程,顺序打印ABC10次
*/
public class PrintThread_ABC_10_1 {
/*
定义标记,初始1为true;
2,3为false->可以打印A,
打印完设置2为true;
1,3为false->可以打印B
打印完设置3为true;
1,2为false->可以打印C
打印完设置1为true;
2,3为false->可以打印A
........每个线程各自循环10次
*/
private static boolean flag1 = true;
private static boolean flag2 = false;
private static boolean flag3 = false;
public static void main(String[] args) {
final PrintThread_ABC_10_1 o = new PrintThread_ABC_10_1();
//创建一个final的本对象用来加锁
Thread t1 = new Thread(() -> {
for (int i = 0;
i < 10;
i++) {//循环10次
while (true){
synchronized (o){
if(!flag1){//如果第一个标记为false时 等待
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName());
flag1 = false;
flag2 = true;
flag3 = false;
o.notifyAll();
//唤醒所有线程
break;
}
}
}
}
},"A");
Thread t2 = new Thread(() -> {
for (int i = 0;
i < 10;
i++) {//循环10次
while (true){
synchronized (o){
if(!flag2){//如果第一个标记为false时 等待
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName());
flag1 = false;
flag2 = false;
flag3 = true;
o.notifyAll();
//唤醒所有线程
break;
}
}
}
}
},"B");
Thread t3 = new Thread(() -> {
for (int i = 0;
i < 10;
i++) {//循环10次
while (true){
synchronized (o){
if(!flag3){//如果第一个标记为false时 等待
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println(Thread.currentThread().getName());
flag1 = true;
flag2 = false;
flag3 = false;
o.notifyAll();
//唤醒所有线程
break;
}
}
}
}
},"C");
t1.start();
t2.start();
t3.start();
}}
【三个线程轮流执行顺序打印ABC】?
方法2:使用原子操作类AtomicInteger
package com.ziyear.exam;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 3个线程,顺序打印ABC10次
*/
public class PrintThread_ABC_10_2 {
static AtomicInteger synObj = new AtomicInteger(0);
public static void main(String[] args) {
TestPrint t1 = new TestPrint(synObj,"A",0);
TestPrint t2 = new TestPrint(synObj,"B",1);
TestPrint t3 = new TestPrint(synObj,"C",2);
t1.start();
t2.start();
t3.start();
}
}class TestPrint extends Thread{
private AtomicInteger syObj;
private String name;
private int flag;
privateint count = 0;
public TestPrint(AtomicInteger syObj, String name, int flag) {
this.syObj = syObj;
this.name = name;
this.flag = flag;
}@Override
public void run() {
while (true) {
synchronized (syObj){
if (syObj.get() % 3 == flag){
syObj.set(syObj.get() + 1);
System.out.println(name);
count++;
syObj.notifyAll();
if (count == 10){
break;
}
}else{
try {
syObj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
方法3:使用信号量
package com.ziyear.exam;
import java.util.concurrent.Semaphore;
/**
* 使用信号量控制打印ABC
*/
public class PrintThread_ABC_10_3 {
public static void main(String[] args) {
PrintABCUsingSemaphore printABC = new PrintABCUsingSemaphore();
new Thread(new Runnable() {
@Override
public void run() {
printABC.printA();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
printABC.printB();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
printABC.printC();
}
}).start();
}
}class PrintABCUsingSemaphore {
/**
* 第一个信号量初始化为1,其他初始化为0 3个信号量分别控制打印ABC
* A有信号量,所以先打印A,打印完A后初始化第二个信号量B
* B有信号量,所以打印B,打印完后初始化第三个信号量
* C有信号量,所以打印C,打印完后初始化第一个信号量
* ...... 每个线程各自在print方法中循环10次
*
*/
private Semaphore semaphoreA = new Semaphore(1);
private Semaphore semaphoreB = new Semaphore(0);
private Semaphore semaphoreC = new Semaphore(0);
public void printA() {
print("A", semaphoreA, semaphoreB);
}
public void printB() {
print("B", semaphoreB, semaphoreC);
}
public void printC() {
print("C", semaphoreC, semaphoreA);
}
private void print(String name, Semaphore currentSemaphore, Semaphore nextSemaphore) {
for (int i = 0;
i < 10;
) {
try {
currentSemaphore.acquire();
System.out.println(name);
i++;
nextSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
推荐阅读
- Integer常量池结合源码解析
- Java基础|Java 打印空心等腰三角形(方法2)
- gradle 每次运行都会下载依赖的解决办法
- 使用vector代替数组
- 如何获取ResultSet的行数和列数
- Java 时间戳格式化
- Java基础|Android开发——JVM、Dalvik以及ART的区别
- XML|XML报文转Map
- Java 8 时间,字符串和Long时间戳互转
- JAVA基础|JAVA基础(TreeMap键是Student值是String案例)