方法一:Object.wait()
package demo1;
public class ThreadDemo2 implements Runnable {
private String lock = new String("lock"); //三个线程共用一个锁
private volatile int state = 0;
@Override
public void run() {
String name = Thread.currentThread().getName();
try {
for (int i = 0; i < 10; i++) {
if (name.equals("A")) {
while (state % 3 != 0) {
synchronized(lock){
lock.wait();}
}
} else if (name.equals("B")) {
while (state % 3 != 1) {
synchronized(lock){
lock.wait();}
}
} else if (name.equals("C")) {
while (state % 3 != 2) {
synchronized(lock){
lock.wait();}
}
}
System.out.print(name); //必须在state改变前输出,否则可能导致乱序
state++;
synchronized(lock){
lock.notifyAll();}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ThreadDemo2 task = new ThreadDemo2();
Thread thread1 = new Thread(task,"A");
Thread thread2 = new Thread(task,"B");
Thread thread3 = new Thread(task,"C");
thread1.start();
thread2.start();
thread3.start();
}
}
方法2:Condition.await()
package demo1;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo implements Runnable {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private volatile int state = 0;
@Override
public void run() {
String name = Thread.currentThread().getName();
lock.lock();
//进入临界区
try {
for (int i = 0; i < 5; i++) {
if (name.equals("A")) {
while ( state % 3 != 0) {
condition.await();//条件不满足,暂时阻塞线程,暂时释放lock
}
} else if (name.equals("B")) {
while (state % 3 != 1) {
condition.await();
}
} else if (name.equals("C")) {
while (state % 3 != 2) {
condition.await();
}
}
System.out.print(name); //在state改变前输出,否则可能导致乱序
state++;
condition.signalAll();//通知正在等待的线程,此时有可能已经满足条件
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();// 记得要释放锁
}
}
public static void main(String[] args) throws InterruptedException {
ThreadDemo task = new ThreadDemo();
Thread thread1 = new Thread(task,"A");
Thread thread2 = new Thread(task,"B");
Thread thread3 = new Thread(task,"C");
thread1.start();
thread2.start();
thread3.start();
}
}
方法3:公平锁 ReentrantLock
package demo1;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDemo3 implements Runnable{
//true表示公平锁,竞争锁的线程依次加入等待队列,先加入队列的先获取锁,关键在于加入等待队列的顺序
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
String name = Thread.currentThread().getName();
try {
if ("B".equals(name)) {
Thread.sleep(10); //确保线程按顺序进入等待队列
}else if ("C".equals(name)) {
Thread.sleep(20);
}
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
lock.lock(); //获取锁
try {
System.out.print(name); //获取线程名字
Thread.sleep(30); //确保A线程等待BC线程进入队列后再进行后续
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
public static void main(String[] args) {
ThreadDemo3 task = new ThreadDemo3();
Thread thread1 = new Thread(task,"A");
Thread thread2 = new Thread(task,"B");
Thread thread3 = new Thread(task,"C");
thread1.start();
thread2.start();
thread3.start();
}
}
网友评论