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 {
//會(huì)一直等待這個(gè)信號(hào)量
word.acquire();
System.out.println((char)i);
text.release();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
通過(guò)信號(hào)量來(lái)控制兩個(gè)線程打印的順序問(wèn)題。
如果兩個(gè)線程打印的長(zhǎng)度不匹配, A1 B 2 C 3 D EF 這樣的形式呢?
通過(guò)定義兩個(gè)變量 boolean 類型的用來(lái)判斷是否結(jié)束,如果結(jié)束了,如果對(duì)方結(jié)束了直接打印即可,就不用再釋放鎖了。
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 {
//會(huì)一直等待這個(gè)信號(hào)量
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();
}
}
}
可重入鎖是什么,可以使用可重入鎖來(lái)實(shí)現(xiàn)交替打印嗎?
可重入鎖是允許同一個(gè)線程多次獲得同一把鎖的同步機(jī)制。
后臺(tái)通過(guò)定義計(jì)數(shù)器來(lái)實(shí)現(xiàn),釋放鎖的時(shí)候計(jì)數(shù)器遞減,只有計(jì)數(shù)器為 0 的時(shí)候才是真正的釋放。
在 Java 中主要是 ReentantLock 類,實(shí)現(xiàn)可重入鎖,手動(dòng)的進(jìn)行 lock 和 unlock,實(shí)現(xiàn)細(xì)粒度的鎖機(jī)制。
直接用 lock 無(wú)法控制兩個(gè)線程交替打印,需要通過(guò) Condition 來(lái)實(shí)現(xiàn)。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class alternatingPrinter2 {
// 創(chuàng)建可重入鎖及兩個(gè) Condition
private static ReentrantLock lock = new ReentrantLock();
// 數(shù)字線程等待條件
private static Condition conditionNumber = lock.newCondition();
// 字母線程等待條件
private static Condition conditionLetter = lock.newCondition();
private static boolean numberTurn = true;
private static final int MAX_NUMBER = 3; // 打印數(shù)字 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();
}
// 打印數(shù)字的線程
static class NumberPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= MAX_NUMBER; i++) {
lock.lock();
try {
// 如果不是數(shù)字打印的時(shí)機(jī),則等待
while (!numberTurn) {
conditionNumber.await();
}
// 打印數(shù)字
System.out.print(i + " ");
// 修改標(biāo)志,輪到字母線程打印
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();
}
}
}
}
}
#交替打印#牛牛的算法專欄,記錄一些算法題