package testthread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* 编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,
* 要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
*
* 使用condition接口、lock类、ReentrantLock类实现线程的通信
*
*/
public class TestLock {
public static void main(String[] args) {
final AlternateDemo ad = new AlternateDemo(); //在使用Java局部内部类或者匿名内部类时,若该类调用了所在方法的局部变量,则该局部变量必须使用final关键字来修饰,否则将会出现编译错误“Cannot refer to a non-final variable * inside an inner class defined in a different method”
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
ad.loopA();
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
ad.loopB();
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
ad.loopC();
System.out.println("-----------------------------------");
}
}
}, "C").start();
}
}
class AlternateDemo {
private int number = 1; //当前正在执行线程的标记
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void loopA() {
lock.lock();//类比去银行办理业务,此行代码相当于先拿到一个办理业务的排队号码
try {
//1. 判断
if (number != 1) {
condition1.await();//线程等待之后,该线程中的其它代码都不会被执行,就直接退出了
}
//2. 打印
System.out.println(Thread.currentThread().getName());
//3. 唤醒
number = 2;
condition2.signal();//尝试去唤醒一个其它等待的满足条件的线程,每个线程都会拿到一次锁,若条件满足将会执行该线程,否则将会等待
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopB() {
lock.lock();
try {
//1. 判断
if (number != 2) {
condition2.await();//等待之后将会释放锁
}
//2. 打印
System.out.println(Thread.currentThread().getName());
//3. 唤醒
number = 3;
condition3.signal();
//condition3.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void loopC() {
lock.lock();
try {
//1. 判断
if (number != 3) {
condition3.await();
}
//2. 打印
System.out.println(Thread.currentThread().getName());
//3. 唤醒
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
相关推荐
- **条件变量(Condition Variable)**:条件变量允许线程等待某个条件满足后再继续执行,常与互斥量一起使用。 - **事件(Event)**:事件可以用来同步线程,线程可以等待事件被触发后继续执行。 - **临界区(Critical ...
4. **并发与同步**:在多线程环境中,数据共享可能导致竞态条件,即多个线程同时访问同一数据,造成结果不一致。因此,需要使用锁、信号量等同步机制来控制对共享资源的访问,确保数据的一致性和完整性。 5. **死锁...
《Java面试宝典Beta5.0》是一本专注于Java编程语言的面试资料,它包含了大量Java面试时可能会遇到的技术问题及其解答,旨在帮助面试者更好地准备和通过Java相关职位的面试。本文将根据提供的文件内容,梳理和详述...
对象浏览器——可配置的树形浏览能够显示同PL/SQL开发相关的全部信息,使用该浏览器可以获取对象描述、浏览对象定义、创建测试脚本以便调试、使能或禁止触发器或约束条件、重新编译不合法对象、查询或编辑表格、...
可配置的树形浏览能够显示同PL/SQL开发相关的全部信息,使用该浏览器可以获取对象描述、浏览对象定义、创建测试脚本以便调试、使能或禁止触发器或约束条件、重新编译不合法对象、查询或编辑表格、浏览数据、在对象...