问题是:启动3个线程顺序打印ABC 10次,不能使用sleep。
方案一:
public class ThreadDemo{public static void main(String[] args) {MyLock lock = new MyLock();
Thread a = new Thread(new MyPrinter("A", "B", lock));
Thread b = new Thread(new MyPrinter("B", "C", lock));
Thread c = new Thread(new MyPrinter("C", "A", lock));
a.start();
b.start();
c.start();
lock.setHolder("A");
}static class MyPrinter implements Runnable {private String myName;
private String nextName;
private final MyLock lock;
public MyPrinter(String myName, String nextName, MyLock lock) {
this.myName = myName;
this.nextName = nextName;
this.lock = lock;
}public void run() {
int count = 3;
while (count > 0) {
if (lock != null && lock.getHolder() != null && lock.getHolder().equals(myName)) {
synchronized (lock) {
System.out.print(myName);
count--;
lock.setHolder(nextName);
}
}}
}
}static class MyLock {public MyLock() {
}
private String holder;
public String getHolder() {
return holder;
}public void setHolder(String holder) {
this.holder = holder;
}
}
}
方案二:
对上一个方案进行修改:把count定义为static,不然每个线程之间可没法共享count变量,且由于是输出后再--,故设置成9比较合适。
public class ThreadDemo{public static void main(String[] args) {MyLock lock = new MyLock();
Thread a = new Thread(new MyPrinter("A", "B", lock));
Thread b = new Thread(new MyPrinter("B", "C", lock));
Thread c = new Thread(new MyPrinter("C", "A", lock));
a.start();
b.start();
c.start();
lock.setHolder("A");
}static class MyPrinter implements Runnable {private String myName;
private String nextName;
private final MyLock lock;
static int count = 9;
public MyPrinter(String myName, String nextName, MyLock lock) {
this.myName = myName;
this.nextName = nextName;
this.lock = lock;
}public void run() {
while (count > 0) {
if (lock != null && lock.getHolder() != null && lock.getHolder().equals(myName)) {
synchronized (lock) {
System.out.print(myName);
count--;
lock.setHolder(nextName);
}
}}
}
}static class MyLock {public MyLock() {
}
private String holder;
public String getHolder() {
return holder;
}public void setHolder(String holder) {
this.holder = holder;
}
}
}
方案三:
本质应该是操作系统中的同步问题,设定好信号量,使用PV元语就可以。要用java实现的话,使用wait()和notify()应该就OK。
public class ThreadDemo {
public static void main(String[] args) {
final int count = 3;
String[] abc = { "a", "b", "c" };
for (int i = 0;
i < abc.length;
i++) {
final String current = abc[i];
final String next = abc[(i + 1) % abc.length];
new Thread(new Runnable() {
public void run() {
for (int j = 0;
j < count;
j++) {
synchronized (current) {
// 等待信号
try {
current.wait();
} catch (InterruptedException e) {
}
System.out.print(current);
// 给下个线程发信号synchronized (next) {
next.notify();
}
}
}
}
}).start();
}
// 通给第一个线程发信号
synchronized (abc[0]) {
abc[0].notify();
}
}
}
可用用如下方式分析(参考)
public class ThreadDemo {
public static void main(String[] args) {
final int count = 3;
String[] abc = { "a", "b", "c" };
for (int i = 0;
i < abc.length;
i++) {
final String current = abc[i];
final String next = abc[(i + 1) % abc.length];
new Thread(new Runnable() {
public void run() {
for (int j = 0;
j < count;
j++) {
synchronized (current) {
// 等待信号
System.out.println(current + "等待信号");
try {
current.wait();
} catch (InterruptedException e) {
}
System.out.println(current + "给下一个线程发信号");
// 给下个线程发信号synchronized (next) {
next.notify();
}
}
System.out.println("第" + j + "次循环");
}
}
}).start();
}
// 通给第一个线程发信号
System.out.println("给第一个线程发信号");
synchronized (abc[0]) {
abc[0].notify();
}
}
}
方案四:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo {
private static Lock lock = new ReentrantLock();
//通过JDK5中的锁来保证线程的访问的互斥
private static int state = 0;
static class ThreadA extends Thread {
@Override
public void run() {
for (int i = 0;
i < 3;
) {
lock.lock();
if (state % 3 == 0) {
System.out.print("A");
state++;
i++;
}
lock.unlock();
}
}
}static class ThreadB extends Thread {
@Override
public void run() {
for (int i = 0;
i < 3;
) {
lock.lock();
if (state % 3 == 1) {
System.out.print("B");
state++;
i++;
}
lock.unlock();
}
}
}static class ThreadC extends Thread {
@Override
public void run() {
for (int i = 0;
i < 3;
) {
lock.lock();
if (state % 3 == 2) {
System.out.print("C");
state++;
i++;
}
lock.unlock();
}
}
}public static void main(String[] args) {
new ThreadA().start();
new ThreadB().start();
new ThreadC().start();
} }
方案五: 使用lock来保证只有一个线程在输出操作, 要保证了state不会被两个线程同时修改, 还可以使用condition, condition的效率可能会更高一些, await会释放lock锁, condition的await和signal与object的wait和notify方法作用类似
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo {
private static Lock lock = new ReentrantLock();
private static int count = 0;
private static Condition A = lock.newCondition();
private static Condition B = lock.newCondition();
private static Condition C = lock.newCondition();
static class ThreadA extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0;
i < 3;
i++) {
while (count % 3 != 0)
A.await();
// 会释放lock锁
System.out.print("A");
count++;
B.signal();
// 唤醒相应线程
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}}static class ThreadB extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0;
i < 10;
i++) {
while (count % 3 != 1)
B.await();
System.out.print("B");
count++;
C.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}}static class ThreadC extends Thread {
@Override
public void run() {
lock.lock();
try {
for (int i = 0;
i < 10;
i++) {
while (count % 3 != 2)
C.await();
System.out.print("C");
count++;
A.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}}public static void main(String[] args) throws InterruptedException {
new ThreadA().start();
new ThreadB().start();
ThreadC threadC = new ThreadC();
threadC.start();
threadC.join();
System.out.println(count);
}
}
【三个线程循环的按顺序打印】
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)