多線程編程重要的就是標誌位Flag,鎖,喚醒
多線程編程注意的兩個地方:標誌位Flag和while
1.判斷
2.幹活
3.通知+喚醒
之前synchronized鎖釋放之後線程瘋搶爭奪資源
但是被Lock,Condition控制後則可以指定線程運行順序,按需接力,不用瘋搶(如果不用Condition依然瘋搶)
三個線程交替打印ABC(五次)
package juc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PrintAbcByOrder {
public static void main(String[] args) {
final PrintAbc printAbc = new PrintAbc();
new Thread(()->{
for (int i = 0; i < 5; i++) {
printAbc.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
printAbc.printB();
}
}, "B").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
printAbc.printC();
}
},"C").start();
}
}
class PrintAbc{
private ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
private int flag = 1;
public void printA(){
lock.lock();
try {
while (flag != 1){
condition1.await();
}
System.out.println("A");
flag = 2;
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (flag != 2){
condition2.await();
}
System.out.println("B");
flag = 3;
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (flag != 3){
condition3.await();
}
System.out.println("C");
flag = 1;
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
進階版 題目:有ABC三個線程,要求線程A打印五次,B10次,C15次,然後,再同樣的順序來兩輪。。。共來十輪
package juc;
import sun.awt.windows.ThemeReader;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class ShareResource{
private int flag = 1;
private ReentrantLock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
//ctrl+alt+t是try catch
public void print5(int totalLoop){
lock.lock();
try {
//1.判斷
while (flag != 1){
condition1.await();
}
//幹活
for (int i = 1;i <= 5; i++) {
System.out.println("線程名字:"+Thread.currentThread().getName()+"\t次數:"+i+"\t輪數:"+totalLoop);
}
//喚醒+通知
flag = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print10(int totalLoop){
lock.lock();
try {
//1.判斷
while (flag != 2){
condition2.await();
}
//幹活
for (int i = 1;i <= 10; i++) {
System.out.println("線程名字:"+Thread.currentThread().getName()+"\t次數:"+i+"\t輪數:"+totalLoop);
}
//喚醒+通知
flag = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print15(int totalLoop){
lock.lock();
try {
//1.判斷
while (flag != 3){
condition3.await();
}
//幹活
for (int i = 1;i <= 15; i++) {
System.out.println("線程名字:"+Thread.currentThread().getName()+"\t次數:"+i+"\t輪數:"+totalLoop);
}
//喚醒+通知
flag = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class ConditionLockDemo {
public static void main(String[] args) {
ShareResource sr = new ShareResource();
new Thread(()->{
for(int i = 1 ; i<=10 ; i++){
sr.print5(i);
}
},"A").start();
new Thread(()->{
for(int i = 1 ; i<=10 ; i++){
sr.print10(i);
}
},"B").start();
new Thread(()->{
for(int i = 1 ; i<=10 ; i++){
sr.print15(i);
}
},"C").start();
}
}