三个线程交替打印
join方法
用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行,为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
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
| package leetcode;
import sort.count;
import java.util.*; import java.util.concurrent.ConcurrentHashMap;
public class Main { public static void main(String[] args) { Thread A = new Thread(new Runnable() { @Override public void run() { System.out.println("A"); } }); Thread B = new Thread(new Runnable() { @Override public void run() { try { A.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("B"); } }); Thread C = new Thread(new Runnable() { @Override public void run() { try { B.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("C"); } }); A.start(); B.start(); C.start(); } }
|
wait方法
通过设置 等待标记 flag
来记录当前拥有锁的是哪个线程, 设置 下一个标记,来记录下一个唤醒的该是哪个线程。
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
| public class Main { public static void main(String[] args) { WaitNotify wn = new WaitNotify(1,5); new Thread(() -> { wn.print("a",1,2); }).start(); new Thread(() -> { wn.print("b",2,3); }).start(); new Thread(() -> { wn.print("c",3,1); }).start(); } } class WaitNotify { private int flag; private int loopNumber;
public WaitNotify(int flag, int loopNumber) { this.flag = flag; this.loopNumber = loopNumber; }
public void print(String str, int waitFlag, int nextFlag) { for (int i = 0; i < loopNumber; i++) { synchronized (this) { while(flag != waitFlag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print(str); flag = nextFlag; this.notifyAll(); } } } }
|
交替循环输出
使用Semaphore(信号量)
有个可以控制线程启动后执行顺序,又简单的实现方式,就是用Semaphore(信号量),它可以控制共享资源的访问个数。
使用方式:
初始化的时候,指定共享资源的个数
1 2 3
| Semaphore semaphore = new Semaphore(1); 获取资源,获取资源后,semaphore资源个数减1,变成0,其他线程再获取资源的时候就会阻塞等待
|
释放资源,semaphore资源个数加1,其他阻塞的线程就可以获取到资源了
代码为:
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
| public class Main { public static void main(String[] args) { Semaphore A = new Semaphore(1); Semaphore B = new Semaphore(0); Semaphore C = new Semaphore(0);
new ThreadDemo(A, B, "A").start(); new ThreadDemo(B, C, "B").start(); new ThreadDemo(C, A, "C").start(); }
static class ThreadDemo extends Thread {
private Semaphore current; private Semaphore next; private String name;
public ThreadDemo(Semaphore current, Semaphore next, String name) { this.current = current; this.next = next; this.name = name; }
@Override public void run() { for (int i = 0; i < 5; i++) { try { current.acquire(); System.out.print(name); } catch (InterruptedException e) { e.printStackTrace(); } next.release(); } } } }
|
使用lock
这种情况下使用锁即可,在上锁之后进行判断 只有满足顺序的时候才打印 不然就解锁走人了 所以三个线程不管谁拿到锁,都必须是按照ABC的顺序进行打印,同时成功之后改变状态,使得顺序能够正常的执行.
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
| public class ThreeThread { private int time; private int state; private Lock lock = new ReentrantLock();
public ThreeThread(int time) { this.time = time; }
public void print(String str, int targetNum) { for (int i = 0; i < time; ) { lock.lock(); if (state % 3 == targetNum) { state++; i++; System.out.print(str); } lock.unlock(); } }
public static void main(String[] args) { ThreeThread th = new ThreeThread(5);
Thread A = new Thread(() -> { th.print("A", 0); });
Thread B = new Thread(() -> { th.print("B", 1); });
Thread C = new Thread(() -> { th.print("C", 2); });
B.start(); A.start(); C.start(); } }
|
park & unpark 版
由于 LockSupport 的 park() 方法可以暂停当前线程,unpark() 方法可以唤醒指定的线程,所以可以在执行完当前线程中的代码后,唤醒指定的线程。
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
| import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock;
public class Test13AlternateOutput { static Thread t1; static Thread t2; static Thread t3; public static void main(String[] args) throws InterruptedException { ParkUnpark pu = new ParkUnpark(5); t1 = new Thread(() -> { pu.print("a",t2); }); t2 = new Thread(() -> { pu.print("b",t3); }); t3 = new Thread(() -> { pu.print("c",t1); }); t1.start(); t2.start(); t3.start(); LockSupport.unpark(t1); } } class ParkUnpark{ private int loopNumber; public ParkUnpark(int loopNumber) { this.loopNumber = loopNumber; } public void print(String str, Thread next) { for (int i = 0; i < loopNumber; i++) { LockSupport.park(); System.out.print(str); LockSupport.unpark(next); } } }
|