tx一面线程交替手撕
import java.util.concurrent.Semaphore;
// 交替打印 1 A 2 B 3 C 这样的线程
public class alternatingPrinter {
public static Semaphore text = new Semaphore(1);
public static Semaphore word=new Semaphore(0);
public static int maxText=3;
public static int maxWord='c';
public static void main(String[] args) {
Thread thread1=new Thread(new printerText());
Thread thread2=new Thread(new printerWord());
thread2.start();
thread1.start();
}
static class printerText implements Runnable {
@Override
public void run() {
for (int i = 1; i <=maxText; i++) {
try {
text.acquire();
System.out.println(i);
word.release();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class printerWord implements Runnable{
@Override
public void run() {
for (int i = 'A'; i <=maxWord ; i++) {
try {
//会一直等待这个信号量
word.acquire();
System.out.println((char)i);
text.release();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
通过信号量来控制两个线程打印的顺序问题。
如果两个线程打印的长度不匹配, A1 B 2 C 3 D EF 这样的形式呢?
通过定义两个变量 boolean 类型的用来判断是否结束,如果结束了,如果对方结束了直接打印即可,就不用再释放锁了。
import java.util.concurrent.Semaphore;
// 交替打印 1 A 2 B 3 C 这样的线程
public class alternatingPrinter {
public static Semaphore text = new Semaphore(1);
public static Semaphore word=new Semaphore(0);
public static int maxText=10;
public static int maxWord='C';
public static boolean isText=false;
public static boolean isWord=false;
public static void main(String[] args) {
Thread thread1=new Thread(new printerText());
Thread thread2=new Thread(new printerWord());
thread2.start();
thread1.start();
}
static class printerText implements Runnable {
@Override
public void run() {
for (int i = 1; i <=maxText; i++) {
try {
if (isWord){
System.out.println(i);
continue;
}
text.acquire();
System.out.println(i);
word.release();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
isText=true;
text.release();
}
}
static class printerWord implements Runnable{
@Override
public void run() {
for (int i = 'A'; i <=maxWord ; i++) {
try {
//会一直等待这个信号量
if (isText){
System.out.println(i);
continue;
}
word.acquire();
System.out.println((char)i);
text.release();
}catch (InterruptedException e){
e.printStackTrace();
}
}
isWord=true;
word.release();
}
}
}
可重入锁是什么,可以使用可重入锁来实现交替打印吗?
可重入锁是允许同一个线程多次获得同一把锁的同步机制。
后台通过定义计数器来实现,释放锁的时候计数器递减,只有计数器为 0 的时候才是真正的释放。
在 Java 中主要是 ReentantLock 类,实现可重入锁,手动的进行 lock 和 unlock,实现细粒度的锁机制。
直接用 lock 无法控制两个线程交替打印,需要通过 Condition 来实现。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class alternatingPrinter2 {
// 创建可重入锁及两个 Condition
private static ReentrantLock lock = new ReentrantLock();
// 数字线程等待条件
private static Condition conditionNumber = lock.newCondition();
// 字母线程等待条件
private static Condition conditionLetter = lock.newCondition();
private static boolean numberTurn = true;
private static final int MAX_NUMBER = 3; // 打印数字 1~3
private static final int MAX_LETTER = 'C'; // 打印字母 A~C
public static void main(String[] args) {
Thread threadNumber = new Thread(new NumberPrinter());
Thread threadLetter = new Thread(new LetterPrinter());
threadNumber.start();
threadLetter.start();
}
// 打印数字的线程
static class NumberPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= MAX_NUMBER; i++) {
lock.lock();
try {
// 如果不是数字打印的时机,则等待
while (!numberTurn) {
conditionNumber.await();
}
// 打印数字
System.out.print(i + " ");
// 修改标志,轮到字母线程打印
numberTurn = false;
// 通知字母线程
conditionLetter.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
// 打印字母的线程
static class LetterPrinter implements Runnable {
@Override
public void run() {
for (char c = 'A'; c <= (char) MAX_LETTER; c++) {
lock.lock();
try {
while (numberTurn) {
conditionLetter.await();
}
System.out.print(c + " ");
numberTurn = true;
conditionNumber.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
#交替打印#牛牛的算法专栏 文章被收录于专栏
牛牛的算法专栏,记录一些算法题