一、题目
有A、B、C 三个线程,A线程 输出“A”,B线程 输出“B”,C线程 输出“C”,要求同时启动3个线程,按照顺序输出“ABC”,循环10次,请使用代码实现。
二、问题分析
- A、B、C 三个线程;这表示我们要使用多线程同步,有人说了这不废话吗。是的,笔者只是想说,多线程的实现,有几种方式,①继承Thread,②实现Runnable 接口、③实现Cannable接口
- A线程 输出“A”,B线程 输出“B”,C线程 输出“C”:这意味着,3个线程之间的执行体run()不同,要想打印的字符串不同有两种方式;
- 采用静态方式,直接打印
- 这种方式,显然,需要3个不同的执行体,也就意味着,我们要实现三个不同的线程类,即3个Class
- 采用构造器参数动态传递方式,将要打印ABC 分别作为参数变量传递进来打印
- 这种方式,只需要1个共同的执行体,也就是只需要实现一个线程类,即1个Class。
- 采用静态方式,直接打印
- 按照顺序输出“ABC”:这表示,我们要控制线程的顺序,控制线程的顺序有哪些?
- 采用共享标识 ,对循环的序号进行控制,如:循环总数 %3 的余数,来指定应该对应的哪一个线程
- 采用互斥锁 :①synchronized和Obejct的wait()、notify,②ReentrantLock和Condition类await 、signal
- 采用原子类型变量 :如,AtomicInteger
- 循环打印10次:这说明,我们需要定义一个线程共享变量static int currentCount,这里不用volatile,是因为volatile,声明变量值的一致性;static声明变量的唯一性。这里需要的是循环打印,是有序的,所以该使用static才对
三、实现
3.1 synchornized
public class CyclePrint002 {
public static void main(String[] args) {
new MyThread(0,"A").start();
new MyThread(1,"B").start();
new MyThread(2,"C").start();
}
//动态变量来控制打印内容
static class MyThread extends Thread{
//共享变量,控制打印总次数
private static Integer curCount=0;
//加锁对象
private static Object obj = new Object();
//要打印的值
private String val;
//是否打印标志位 0-A,1-B,2-C
private Integer flag;
MyThread(int flag,String val){
this.flag = flag;
this.val = val;
}
@Override
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("这是线程"+val+"的第"+i+"次");
synchronized (obj){
System.out.println("这是线程"+val+"的第"+i+"次获取到锁");
while(curCount%3 != flag){
try{
// System.out.println("这是线程"+val+"的第"+i+"次获取到锁后进入等待了");
obj.wait();
// System.out.println("这是线程"+val+"的第"+i+"次获取到锁后进入等待了然后继续执行了");
}
catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println(val);
curCount++;
obj.notifyAll(); // 调用notifyAll方法
}
}
}
}
}
3.2 ReentrantLock
static class MyThreadLock extends Thread{
static ReentrantLock lock = new ReentrantLock();
private static int curCount=0;
private int flag;
private String val;
MyThreadLock(int flag,String val){
this.flag=flag;
this.val=val;
}
@Override
public void run(){
for (int i = 0; i < 10; ) {
try{
lock.lock();
while (curCount%3==flag){
System.out.println(val);
curCount++;
i++;
}
}
finally {
lock.unlock();
}
}
}
}
3.3 ReentrantLock+一个Condition
public static void main(String[] args) {
new MyThreadLock(0,"A").start();
new MyThreadLock(1,"B").start();
new MyThreadLock(2,"C").start();
}
static class MyThreadLock extends Thread{
static ReentrantLock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
private static int curCount=0;
private int flag;
private String val;
MyThreadLock(int flag,String val){
this.flag=flag;
this.val=val;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// System.out.println(val+"--thread this i--"+i);
// System.out.println(val+"--thread get lock");
lock.lock();
// System.out.println(val+"--thread get lock success");
try{
while(curCount%3 != flag){
// System.out.println(val+"--thread await");
condition.await();
// System.out.println(val+"--thread await over");
}
System.out.println(val);
curCount++;
// System.out.println(val+"--thread curCount::"+curCount);
// System.out.println(val+"--thread signalAll");
condition.signalAll();
// System.out.println(val+"--thread signalAll over");
}
catch (InterruptedException e){
e.printStackTrace();
}
finally {
lock.unlock();
// System.out.println(val+"--thread unlock over");
}
// System.out.println(val+"--thread this end i--"+i);
}
}
}
3.4 ReentrantLock+三个Condition
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try{
lock.lock();
conditionA.signal();
System.out.println("A");
conditionC.await();
}
catch (InterruptedException e){
e.printStackTrace();
}
finally {
lock.unlock();
}
}
},"Thread--A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try{
lock.lock();
conditionB.signal();
System.out.println("B");
conditionA.await();
}
catch (InterruptedException e){
e.printStackTrace();
}
finally {
lock.unlock();
}
}
},"Thread--B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try{
lock.lock();
conditionC.signal();
System.out.println("C");
conditionB.await();
}
catch (InterruptedException e){
e.printStackTrace();
}
finally {
lock.unlock();
}
}
},"Thread--C").start();
}
3.5 Semaphore
public static void main(String[] args) {
//用Semaphore
Semaphore semaphoreA = new Semaphore(1);
Semaphore semaphoreB = new Semaphore(0);
Semaphore semaphoreC = new Semaphore(0);
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
semaphoreA.acquire();
System.out.println("A");
semaphoreB.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
semaphoreB.acquire();
System.out.println("B");
semaphoreC.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
semaphoreC.acquire();
System.out.println("C");
semaphoreA.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}