固定运行顺序
问题:先打印2后打印1
- 使用wait()和notify()组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package juc.thread;
public class shunxu { static Object lock = new Object(); static boolean flag = false; public static void main(String[] args) { Thread thread = new Thread(() -> { synchronized (lock){ while(!flag){ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("1"); }
},"t1");
Thread thread2 = new Thread(() -> { synchronized (lock){ System.out.println("2"); flag = true; lock.notify(); } },"t2"); thread.start(); thread2.start(); } }
|
- 使用park()和unpark()组合
park()和unpark()以线程为单位来阻塞和唤醒线程,而notify只能随机唤醒一个线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class shunxu { public static void main(String[] args) { Thread thread = new Thread(() -> { LockSupport.park(); System.out.println("1"); },"t1");
Thread thread2 = new Thread(() -> { System.out.println("2"); LockSupport.unpark(thread); },"t2"); thread.start(); thread2.start(); } }
|
交替输出
问题:交替输出abc,假设循环5次,则输出结果是abcabcabcabcabc
- 使用wait()¬ify()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class shunxu { public static void main(String[] args) { waitnotify a1 = new waitnotify(1,5); new Thread(()->{ a1.print("a",1,2); }).start(); new Thread(()->{ a1.print("b",2,3); }).start(); new Thread(()->{ a1.print("c",3,1); }).start(); }
} class waitnotify{ static int flag; static int num; public waitnotify(int flag,int num){ this.num = num; this.flag = flag; }
public void print(String str,int flag,int nextflag){ for (int i = 0; i < num; i++) { synchronized (this){ while(!(flag == this.flag)){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(str); this.flag = nextflag; this.notifyAll(); } } } }
|
- 使用ReentrantLock,创建多个休息室,先让所有线程进入休息室等待,主线程唤醒一个线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package juc.thread;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock;
public class shunxu { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); Condition c1 = lock.newCondition(); Condition c2 = lock.newCondition(); Condition c3 = lock.newCondition(); waitnotify a1 = new waitnotify(5,lock);
new Thread(()->{ a1.print("a",c1,c2); }).start(); new Thread(()->{ a1.print("b",c2,c3); }).start(); new Thread(()->{ a1.print("c",c3,c1); }).start();
lock.lock(); try{ c1.signal(); }finally { lock.unlock(); }
}
} class waitnotify{ int num; static ReentrantLock lock; public waitnotify(int num,ReentrantLock lock){ this.num = num; this.lock = lock; }
public void print(String str, Condition c1,Condition c2){ for (int i = 0; i < num; i++) { lock.lock(); try{ c1.await(); System.out.print(str); c2.signal(); }catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } } }
|
三个线程交替输出1~99
重点在于设置volatile保证共享变量的可见性和有序性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| package juc.thread;
public class parctice {
public static void main(String[] args) { waitNotify w = new waitNotify(1,1); new Thread(()->{ w.print(1,2); },"t1").start(); new Thread(()->{ w.print(2,3); },"t2").start(); new Thread(()->{ w.print(3,1); },"t3").start(); } } class waitNotify{ private int flag; private volatile int res;
public waitNotify(int flag,int res){ this.flag = flag; this.res = res; }
public void print(int flag,int nextflag){ while(res < 100) { synchronized (this){ while(!(flag == this.flag)){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } if(res > 99){ return; } System.out.println(Thread.currentThread().getName()+"["+res+"]"); synchronized (this){ res++; this.flag = nextflag; notifyAll(); } } } } }
|