目前有個任務(wù)需要對數(shù)據(jù)進(jìn)行一個循環(huán)處理,那么就需要多線程順序觸發(fā)的問題了.
這里以順序打印為例子對常見的多線程順序處理做個總結(jié),拿出兩個非常常用的方式.
方法一: 資源+鎖
核心點(diǎn):
1.鎖共同資源lock
2.通過while循環(huán)判斷每次被喚醒是否要再次阻塞
public class ThreadsPrintOrder {
private static Integer curr = 0;
private static String[] strs = new String[]{"A", "B", "C"};
private static int count = 10;
static Object lock=new Object();
public static void main(String[] args) {
final Thread a = getThread("A");
final Thread b = getThread("B");
final Thread c = getThread("C");
a.start();
b.start();
c.start();
}
private static Thread getThread(String threadName) {
return new Thread(() -> {
synchronized (lock) {
for (int i = 0; i < count; i++) {
while (!strs[curr%strs.length].equals(threadName)) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName());
curr++;
lock.notifyAll();
}
}
}, threadName);
}
}
方法二 一個ReentrantLock加多個conditon實(shí)現(xiàn)(推薦鉴嗤,安全性葵第,性能和可讀性較高)
上面那種方法有個缺點(diǎn)就是每個線程被喚醒是隨機(jī)的,每次被喚醒的可能是我們不想打印的線程,需要它再次自我關(guān)閉.
而ReentrantLock的獨(dú)特效果可以做到結(jié)合conditon實(shí)現(xiàn)定向喚醒.
public class ThreadsPrintOrder_m2 {
static int count=10;
public static void main(String[] args) {
LockOrderPrint lockOrder=new LockOrderPrint();
new Thread(()->{
for (int i = 0; i <count ; i++) {
lockOrder.printA();
}
}).start();
new Thread(()->{
for (int i = 0; i <count ; i++) {
lockOrder.printB();
}
}).start();
new Thread(()->{
for (int i = 0; i <count ; i++) {
lockOrder.printC();
}
}).start();
}
}
class LockOrderPrint {
int flag=0;
Lock lock=new ReentrantLock();
Condition conditionA=lock.newCondition();
Condition conditionB=lock.newCondition();
Condition conditionC=lock.newCondition();
public void printA(){
lock.lock();
try {
while (flag%3!=0){
try {
conditionA.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
flag++;
conditionB.signal();
}catch (Exception exce){
exce.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (flag%3!=1){
try {
conditionB.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
flag++;
conditionC.signal();
}catch (Exception exce){
exce.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (flag%3!=2){
try {
conditionC.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
flag++;
conditionA.signal();
}catch (Exception exce){
exce.printStackTrace();
}finally {
lock.unlock();
}
}
}