前言
记录多线程实现ABC
一、原子类加循环判断
package mainin.thread;
import java.util.concurrent.atomic.AtomicInteger;
public class Test1 {
private static AtomicInteger order = new AtomicInteger(1);
public static void main(String[] args) {
Thread A = new Thread(()->{
// 不断循环一直判断
while (true){
// order为1的时候进入
if(order.get()==1){
System.out.println("A");
order.getAndIncrement();
// 输出A 并且跳出死循环,结束本线程
break;
}
}
});
Thread B = new Thread(()->{
// 不断循环一直判断
while (true){
// order为2的时候进入也就是上个线程自增1后进入本线程
if(order.get()==2){
System.out.println("B");
order.getAndIncrement();
break; //跳出循环
}
}
});
Thread C = new Thread(()->{
// 不断循环一直判断
while (true){
// order为3的时候进入
if(order.get()==3){
System.out.println("C");
order.getAndIncrement();
break;//跳出循环
}
}
});
A.start();
B.start();
C.start();
}
}
多次运行结果如下:
总结:这种方法是最初级的办法,也是最容易理解的办法,但是对cpu的消耗是很大的,因为一直都在死循环while(true)判断。
二、使用coundownlatch
package mainin.thread;
import java.util.concurrent.CountDownLatch;
public class Test2 {
public static void main(String[] args) {
CountDownLatch countDownLatch1 = new CountDownLatch(1);
CountDownLatch countDownLatch2 = new CountDownLatch(1);
CountDownLatch countDownLatch3 = new CountDownLatch(1);
Thread A = new Thread(()->{
try {
// 本线程阻塞,在线程外 countdown
countDownLatch1.await();
System.out.println("A");
//释放B线程
countDownLatch2.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
});
Thread B = new Thread(()->{
try {
// 本线程阻塞
countDownLatch2.await();
System.out.println("B");
//释放最后一个线程
countDownLatch3.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
});
Thread C = new Thread(()->{
try {
// C线程阻塞
countDownLatch3.await();
System.out.println("C");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
}
});
A.start();
B.start();
C.start();
//开始释放第一个线程
countDownLatch1.countDown();
}
}
多次执行结果如下:
三、使用thread.join方式
package mainin.thread;
public class Test3 {
public static void main(String[] args) {
ThreadA A= new ThreadA();
ThreadB B = new ThreadB();
ThreadC C = new ThreadC();
B.setA(A);
C.setB(B);
// C执行前--》B B执行前---》A
//这样无论是从哪个线程开始,都能依次去找上一个执行的线程,就可以达到顺序执行的目的。
A.start();
B.start();
C.start();
}
static class ThreadA extends Thread{
@Override
public void run() {
System.out.println("A");
}
}
static class ThreadB extends Thread{
private ThreadA a;
@Override
public void run() {
try {
// B执行前把A加入进来,先把A执行了
a.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
}
public void setA(ThreadA a) {
this.a = a;
}
}
static class ThreadC extends Thread{
private ThreadB b;
@Override
public void run() {
try {
// C执行前把B加入进来,先把B执行了
b.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
}
public void setB(ThreadB b) {
this.b = b;
}
}
}
多次执行结果如图:
四、completeFuture方式执行
package mainin.thread;
import com.sun.xml.internal.ws.util.CompletedFuture;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
public class Test4 {
public static void main(String[] args) {
CompletableFuture cf = CompletableFuture.runAsync(() -> {
System.out.println("A");
});
CompletableFuture b = cf.thenApply((C) -> {
System.out.println("B");
return null;
});
CompletableFuture c = b.thenApply((C) -> {
System.out.println("C");
return null;
});
}
}
多次运行结果如图:
五 使用condition实现
package mainin.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Test5 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
Condition condition3 = reentrantLock.newCondition();
Thread A = new Thread(()->{
reentrantLock.lock();
try {
//当前线程1等待 由主线程也就main函数线程唤醒
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A");
//唤醒下一个线程
condition2.notify();
reentrantLock.unlock();
});
Thread B = new Thread(()->{
reentrantLock.lock();
try {
//线程B等待,等待线程A唤醒
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B");
//唤醒线程C
condition3.notify();
reentrantLock.unlock();
});
Thread C = new Thread(()->{
reentrantLock.lock();
try {
// 当前线程等待
condition3.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
reentrantLock.unlock();
});
A.start();
B.start();
C.start();
condition1.notify();
}
}
多次执行后结果截图:
总结
1.使用了五种方式进行这个简单功能的实现,进一步增强对于多线程相关类的理解。
2.其中condition和countdownlatch的实现方式思想是类似的,
3.其实如果不是为了练习多线程,其实最简单的直接一个线程三个systemout就完了,这个是最简单的办法,也就是串行就完了,所以实际意义上的使用不会这样子实现的,也就是为了练习而已。