tip: 作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。
一、同步模式之顺序控制线程执行
同步模式是指在多线程编程中,为了保证线程之间的协作和正确性,需要对线程的执行顺序进行控制。顺序控制线程执行是一种同步模式,它通过控制线程的等待和唤醒来实现线程的有序执行。
顺序控制线程执行的实现方式很多,其中比较常用的有以下几种:
join()方法:join()方法可以让一个线程等待另一个线程执行完毕后再执行。使用join()方法可以保证线程的有序执行。
wait()和notify()方法:wait()方法可以让一个线程等待另一个线程的通知,而notify()方法可以通知等待的线程继续执行。使用wait()和notify()方法可以实现线程的等待和唤醒,从而实现线程的有序执行。
synchronized关键字:synchronized关键字可以让一个线程独占一个对象,从而实现线程的同步执行。在多个线程访问共享资源时,使用synchronized关键字可以保证线程的有序执行。
顺序控制线程执行的实现方式不同,适用于不同的场景。在实际开发中,需要根据具体的需求选择合适的实现方式。
二、代码样例
以下是一个简单的 Java 样例代码,用于演示同步模式之顺序控制线程执行的实现方式:
package com.pany.camp.thread.sync;
public class SyncExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程1开始执行");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1继续执行");
}
});
Thread t2 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程2开始执行");
lock.notify();
System.out.println("线程2通知线程1继续执行");
}
});
t1.start();
t2.start();
}
}
三、三个线程分别输出a、b、c,按顺序输出abcabcabc (大厂机试题)
package com.pany.camp.thread.sync;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncAbc {
private static Lock lock = new ReentrantLock();
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
private static Condition conditionC = lock.newCondition();
private static volatile int count = 0;
public static void main(String[] args) {
Thread threadB = new Thread(new PrintTask("b", 1, conditionB, conditionC));
Thread threadC = new Thread(new PrintTask("c", 2, conditionC, conditionA));
Thread threadA = new Thread(new PrintTask("a", 0, conditionA, conditionB));
threadA.start();
threadB.start();
threadC.start();
}
static class PrintTask implements Runnable {
private String content;
private int order;
private Condition current;
private Condition next;
public PrintTask(String content, int order, Condition current, Condition next) {
this.content = content;
this.order = order;
this.current = current;
this.next = next;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (count % 3 != order) {
current.await();
}
System.out.print(content);
count++;
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
我们使用了 Lock 和 Condition 来实现线程的同步,其中 Lock 用于保证线程的互斥访问,Condition 用于实现线程的等待和唤醒。count 变量用于记录当前应该输出哪个字符,order 变量用于记录当前线程应该输出哪个字符。在每个线程的 run 方法中,首先获取锁,然后判断当前应该输出哪个字符,如果不是当前线程应该输出的字符,则当前线程进入等待状态。如果是当前线程应该输出的字符,则输出该字符,将 count 加 1,并通知下一个线程继续执行。最后释放锁。