算法之字符串多線程交替輸出

字符串兩個線程交替打印輸出

算法之字符串多線程交替輸出

字符串 “20190425”, 1到100數字使用兩個線程嚴格交替打印?

解法一:wait and notify

  • 思路:”20190425” 兩個線程交替打印
  • 一個打印線程輸出奇數INDEX
  • 一個打印線程輸出偶數INDEX
  • 線程執行中用wait實現等待,notify實現喚醒
  • 避免時間過短,輸出亂序,Sleep一定的時間
public class T1 {
public static void main(String[] args) {
T1 demo = new T1();
Thread t1 = new Thread(demo::print1);
Thread t2 = new Thread(demo::print2);
t1.start();
t2.start();
}
public synchronized void print1() {
String s = "20190425";
//一個打印線程輸出奇數INDEX
for (int i = 0; i < s.length(); i += 2) {
print(s, i);
}
}
public synchronized void print2() {
String s = "20190425";
//一個打印線程輸出奇數INDEX
for (int i = 1; i < s.length(); i += 2) {
print(s, i);
}

}
private void print(String s, int i) {
char c = s.charAt(i);
this.notify();//線程執行中用wait實現等待,notify實現喚醒
System.out.println("thead id:" + Thread.currentThread().getId() + "," + c);
try {
this.wait();
Thread.sleep(100);//避免時間過短,輸出亂序,Sleep一定的時間
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

解法二:利用CAS

  • 思路:利用原子計數器AtomicInteger和volatile變量來實現
  • 使用了CAS實現,避免線程的上下文的切換。
  • 使用volatile的變量,保證不會出現變量可見性的問題。
/**
* //性能更優:利用原子計數器AtomicInteger和volatile變量來實現
* - 使用了CAS實現,避免線程的上下文的切換。
* - 使用volatile的變量,保證不會出現變量可見性的問題。
*/
public class ThreadPrint2 {
private static AtomicInteger num = new AtomicInteger(0);
private static volatile boolean flag = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {

for (; 100 > num.get(); ) {
if (!flag && (num.get() == 0 || num.incrementAndGet() % 2 == 0)) { //偶數輸出
try {
Thread.sleep(100); //避免打印過快導致混亂輸出
} catch (InterruptedException e) {
}
System.out.println(num.get());
flag = true;
}
}
});
Thread t2 = new Thread(() -> {
for (; 100 > num.get(); ) {
if (flag && (num.incrementAndGet() % 2 != 0)) { //奇數輸出
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
System.out.println(num.get());
flag = false;
}
}
});
t1.start();
t2.start();
}
}

解法三:利用volatitle變量替換CAS

  • 思路:
  • 利用volatile代替CAS變量,減輕CAS的消耗,++num不是原子性的,但不受影響,因為有flag變量控制。
  • 而num必須是volatile,否剛會出現可見性問題。
//題目:多線程嚴格交替打印字符串 20190425
//利用volatile代替CAS變量,減輕CAS的消耗,++num不是原子性的,但不受影響,因為有flag變量控制。

//而num必須是volatile,否剛會出現可見性問題。
//https://www.cnblogs.com/stateis0/p/9091254.html
public class ThreadPrint3 {
private static volatile int num = 0;
private static volatile boolean flag = false;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for(; 100 > num;) {
if(!flag && (num == 0 || ++num % 2 == 0)) {
try {
Thread.sleep(100);
} catch(InterruptedException e) {
}
System.out.println(num);
flag = true;
}
}
});
Thread t2 = new Thread(() -> {
for(; 100 > num;) {
if(flag && (++num % 2 != 0)) {
try {
Thread.sleep(100);
} catch(InterruptedException e) {
}
System.out.println(num);
flag = false;
}
}
});
t1.start();
t2.start();
}
}


分享到:


相關文章: