基于JOIN
线程自己的逻辑与控制逻辑分离,执行逻辑不受影响,耦合性最低
Thread t1 = new Thread(new T1());
t1.start();
t1.join();
Thread t2 = new Thread(new T2());
t2.start();
t2.join();
Thread t3 = new Thread(new T3());
t3.start();
t3.join();
基于信号量
每个线程需要知道自己运行所需要的信号量,以及开启下一个线程的信号量,
有点像 chain 模式。 执行逻辑和控制逻辑有耦合。
public static void main(String[] args) throws Exception {
Semaphore lock1 = new Semaphore(1);
Semaphore lock2 = new Semaphore(1);
Semaphore lock3 = new Semaphore(1);
lock2.acquire();
lock3.acquire();
for(int i =0; i < 10; i++) {
Thread t1 = new Thread(new T1(lock1,lock2));
Thread t2 = new Thread(new T2(lock2, lock3));
t2.start();
Thread t3 = new Thread(new T3(lock3, lock1));
t3.start();
t1.start();
}
}
static class T1 implements Runnable{
public Semaphore nextLock;
Semaphore current;
public T1(Semaphore current, Semaphore nextlock){
this.nextLock=nextlock;
this.current =current;
}
@Override
public void run() {
try {
current.acquire();
System.out.println("Sleep");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-111");
nextLock.release();
}
}
static class T2 implements Runnable{
public Semaphore nextLock;
Semaphore current;
public T2(Semaphore current, Semaphore nextlock){
this.nextLock=nextlock;
this.current =current;
}
@Override
public void run() {
try {
current.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-222");
nextLock.release();
}
}
static class T3 implements Runnable{
public Semaphore nextLock;
Semaphore current;
public T3(Semaphore current, Semaphore nextlock){
this.nextLock=nextlock;
this.current =current;
}
@Override
public void run() {
try {
current.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-333");
nextLock.release();
}
}
基于countDownlatch
和信号量的思路是一样的,每个线程需要等待自己 latch,并且完成任务之后,对下一个latch 进行 countDown。
public static void main(String[] args) throws Exception {
for(int i =0; i < 1; i++) {
CountDownLatch c1 = new CountDownLatch(1);
CountDownLatch c2 = new CountDownLatch(1);
Thread t1 = new Thread(new T1(c1));
Thread t2 = new Thread(new T2(c1,c2));
t2.start();
Thread t3 = new Thread(new T3(c2));
t3.start();
t1.start();
}
}
static class T1 implements Runnable{
public CountDownLatch c1;
public T1(CountDownLatch c1){
this.c1=c1;
}
@Override
public void run() {
try {
System.out.println("Sleep");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-111");
c1.countDown();
}
}
static class T2 implements Runnable{
public CountDownLatch c1;
CountDownLatch c2;
public T2(CountDownLatch c1, CountDownLatch c2){
this.c1=c1;
this.c2 =c2;
}
@Override
public void run() {
try {
c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-222");
c2.countDown();
}
}
static class T3 implements Runnable{
CountDownLatch c2;
public T3(CountDownLatch c2){
this.c2 =c2;
}
@Override
public void run() {
try {
c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-333");
}
}
基于条件变量
条件变量是lock+ condition, 是最接近用 notify+wait 来实现的方式。
每个lock 可以穿件多个条件变量, 每个 条件变量 await 都能够释放lock。
但是condition 的singal 方法可以精确的唤醒等待的线程。这是条件变量现对于notify的优势,可以更加精准的控制。
public static void main(String[] args) throws Exception {
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Thread t1 = new Thread(new T1(lock, condition1));
Thread t2 = new Thread(new T2(lock, condition1,condition2));
t2.start();
Thread t3 = new Thread(new T3(lock, condition2,null));
t3.start();
t1.start();
}
static class T1 implements Runnable{
public Lock lock;
Condition nextCondition;
public T1(Lock lock, Condition nextCondition){
this.lock = lock;
this.nextCondition =nextCondition;
}
@Override
public void run() {
try {
lock.lock();
System.out.println("Sleep");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-111");
nextCondition.signal();
lock.unlock();
}
}
static class T2 implements Runnable{
public Lock lock;
Condition nextCondition;
Condition currentCondition;
public T2(Lock lock, Condition currentCondition,Condition nextCondition){
this.lock = lock;
this.nextCondition =nextCondition;
this.currentCondition = currentCondition;
}
@Override
public void run() {
lock.lock();
try {
currentCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-222");
nextCondition.signal();
lock.unlock();
}
}
static class T3 implements Runnable{
public Lock lock;
Condition nextCondition;
Condition currentCondition;
public T3(Lock lock, Condition currentCondition,Condition nextCondition){
this.lock = lock;
this.nextCondition =nextCondition;
this.currentCondition = currentCondition;
}
@Override
public void run() {
lock.lock();
try {
currentCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I am T-333");
lock.unlock();
}
}