前言
多个 线程 执行如何保证顺序,这里总结了4种方法:
1、线程的协作(联合)机制实现。
2、线程的等待和唤醒机制实现,缺点:wait和notify不能脱离 synchronized 代码块或者synchronized方法独自运行。
3、使用 Lock 及Condition对象实现。
4、使用 lock Support实现, 阻塞:LockSupport.park()和唤醒:LockSupport.unpark(thread)。
实现
方式1:线程的协作(联合)机制
public class Thread Demo01 {
public static void main(String[] args) {
System.out.println("▶▶▶▶▶ 主程序开始");
Thread thread = null ;
for (int i = 0; i < 9; i++) {
MyRunnable myRunnable = new MyRunnable("我是线程:" + (i + 1), thread);
Thread exeThread = new Thread(myRunnable);
exeThread.start();
thread = exeThread;
}
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable implements Runnable {
private String name;
private Thread thread;
MyRunnable(String name, Thread thread) {
this.name = name;
this.thread = thread;
}
@Override
public void run() {
if (thread != null) {
try {
// 把指定的线程加入到当前线程
thread.join();
} catch (Interrupted Exception e) {
e.printStackTrace();
}
}
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + this.name + "]正在执行中.");
}
}
}
方式2:线程的等待和唤醒机制
import java .util.concurrent.TimeUnit;
public class ThreadDemo0203 {
public static void main(String[] args) {
System.out.println("▶▶▶▶▶ 主程序开始");
Object curtLock = null;
Object nextLock = null;
for (int i = 0; i < 9; i++) {
if (i == 0) {
// 第一个
curtLock = null;
nextLock = new Object();
} else if (i == 8) {
// 最后一个
curtLock = nextLock;
nextLock = null;
} else {
// 中间态
curtLock = nextLock;
nextLock = new Object();
}
MyRunnable myRunnable = new MyRunnable("我是线程:" + (i + 1), curtLock, nextLock);
Thread exeThread = new Thread(myRunnable);
exeThread.start();
}
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable implements Runnable {
private String name;
private Object curtLock;
private Object nextLock;
MyRunnable(String name, Object curtLock, Object nextLock) {
this.name = name;
this.curtLock = curtLock;
this.nextLock = nextLock;
}
@Override
public void run() {
if (this.curtLock == null) {
// 先等待一下再执行
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this.nextLock) {
// 业务代码
execute(this.name);
// 发出通知
if (this.nextLock != null) {
this.nextLock.notify();
}
}
} else {
synchronized (this.curtLock) {
// 进入等待
try {
this.curtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 业务代码
execute(this.name);
// 发出通知
if (this.nextLock != null) {
synchronized (this.nextLock) {
this.nextLock.notify();
}
}
}
}
}
private void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
}
循序渐进1
import java.util.concurrent.TimeUnit;
public class ThreadDemo02 {
public static void main(String[] args) {
System.out.println("▶▶▶▶▶ 主程序开始");
// wait + notify不能脱离synchronized代码块或者方法;
// wait + notify顺序不能颠倒,只能先等待后唤醒
Object lock = new Object();
new Thread(new MyRunnable1("线程1", lock)).start();
new Thread(new MyRunnable2("线程2", lock)).start();
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable1 implements Runnable {
private String name;
private Object lock;
MyRunnable1(String name, Object lock) {
this.name = name;
this.lock = lock;
}
@Override
public void run() {
// wait + notify顺序不能颠倒,只能先等待后唤醒
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
execute(this.name);
lock.notify();
}
}
}
static class MyRunnable2 implements Runnable {
private String name;
private Object lock;
MyRunnable2(String name, Object lock) {
this.name = name;
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
execute(this.name);
}
}
}
private static void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
循序渐进2
import java.util.concurrent.TimeUnit;
public class ThreadDemo0202 {
public static void main(String[] args) {
System.out.println("▶▶▶▶▶ 主程序开始");
Object lock = new Object();
Object lock2 = new Object();
new Thread(new MyRunnable1("线程1", lock)).start();
new Thread(new MyRunnable2("线程2", lock, lock2)).start();
new Thread(new MyRunnable3("线程3", lock2)).start();
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable1 implements Runnable {
private String name;
private Object lock;
MyRunnable1(String name, Object lock) {
this.name = name;
this.lock = lock;
}
@Override
public void run() {
// wait + notify顺序不能颠倒,只能先等待后唤醒
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
execute(this.name);
lock.notify();
}
}
}
static class MyRunnable2 implements Runnable {
private String name;
private Object lock;
private Object lock2;
MyRunnable2(String name, Object lock, Object lock2) {
this.name = name;
this.lock = lock;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (this.lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
execute(this.name);
//
synchronized (this.lock2) {
lock2.notify();
}
}
}
}
static class MyRunnable3 implements Runnable {
private String name;
private Object lock2;
MyRunnable3(String name, Object lock2) {
this.name = name;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (this.lock2) {
try {
lock2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
execute(this.name);
}
}
}
private static void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
方式3:互斥锁Lock及Condition
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo03 {
public static void main(String[] args) {
// lock和await和signal必须一起使用才行,await和 signal 不能脱离lock单独使用;
// 必须要先等待,后唤醒;顺序不能颠倒。
System.out.println("▶▶▶▶▶ 主程序开始");
Lock lock = new ReentrantLock();
Condition curtCondition = null;
Condition nextCondition = null;
for (int i = 0; i < 9; i++) {
if (i == 0) {
// 第一个
curtCondition = null;
nextCondition = lock.newCondition();
} else if (i == 8) {
// 最后一个
curtCondition = nextCondition;
nextCondition = null;
} else {
// 中间态
curtCondition = nextCondition;
nextCondition = lock.newCondition();
}
MyRunnable myRunnable = new MyRunnable("我是线程:" + (i + 1), lock, curtCondition, nextCondition);
Thread exeThread = new Thread(myRunnable);
exeThread.start();
}
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable implements Runnable {
private String name;
private Lock lock;
private Condition curtCondition;
private Condition nextCondition;
public MyRunnable(String name, Lock lock, Condition curtCondition, Condition nextCondition) {
this.name = name;
this.lock = lock;
this.curtCondition = curtCondition;
this.nextCondition = nextCondition;
}
@Override
public void run() {
if (curtCondition == null) {
// 先等待一下再执行
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
lock.lock();
// 执行业务
this.execute(this.name);
// 发出通知
if (this.nextCondition != null) {
// lock和await和signal必须一起使用才行,await和signal不能脱离lock单独使用
this.nextCondition.signal();
}
} finally {
lock.unlock();
}
} else {
try {
lock.lock();
// 进入等待
try {
// lock和await和signal必须一起使用才行,await和signal不能脱离lock单独使用
this.curtCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlock();
}
// 执行业务
this.execute(this.name);
try {
lock.lock();
// 发出通知
if (this.nextCondition != null) {
this.nextCondition.signal();
}
} finally {
lock.unlock();
}
}
}
private void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
}
方式4:LockSupport类
import java.util.concurrent.locks.LockSupport;
public class ThreadDemo0402 {
public static void main(String[] args) {
System.out.println("▶▶▶▶▶ 主程序开始");
Thread nextThread = null;
for (int i = 8; i > 0; i--) {
int status = (i == 1) ? 1 : 0;
Thread exeThread = new Thread(new MyRunnable("我是线程:" + (i), status, nextThread));
exeThread.start();
nextThread = exeThread;
}
System.out.println("◀◀◀◀◀ 主程序结束");
}
static class MyRunnable implements Runnable {
private String name;
private int status;
private Thread thread;
MyRunnable(String name, int status, Thread thread) {
this.name = name;
this.status = status;
this.thread = thread;
}
@Override
public void run() {
if (status == 1) {
// 业务代码
this.execute(this.name);
// 唤醒线程
if (thread != null) {
LockSupport.unpark(thread);
}
} else if (status == 0) {
// 阻塞
LockSupport.park();
// 业务代码
this.execute(this.name);
// 唤醒线程
if (thread != null) {
LockSupport.unpark(thread);
}
}
}
private void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
}
循序渐进:
import java.util.concurrent.locks.LockSupport;
public class ThreadDemo04 {
public static void main(String[] args) {
// Posix线程库
// 阻塞线程 LockSupport.park();
// 唤醒线程: LockSupport.unpark();
Thread thread2 = new Thread(new MyRunnable("线程2", null));
Thread thread1 = new Thread(new MyRunnable("线程1", thread2));
thread1.start();
thread2.start();
}
static class MyRunnable implements Runnable {
private String name;
private Thread thread;
MyRunnable(String name, Thread thread) {
this.name = name;
this.thread = thread;
}
@Override
public void run() {
if (thread == null) {
// 阻塞
LockSupport.park();
// 业务代码
this.execute(this.name);
} else {
// 业务代码
this.execute(this.name);
// 唤醒
LockSupport.unpark(thread);
}
}
private void execute(String name) {
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + name + "]正在执行中.");
}
}
}