线程Thread(JAVA) 篇七 线程间通信(wait(),notify(),notifyAll())–等待唤醒机制
其实在JAVA1.5以后关于同步和锁做了封装。如图所示

通过查看API java.util.concurrent.locks包中的Lock接口可以知道:
Lock实现提供比使用synchronized方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition。
并且查看到了Lock的惯用方式:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
通过查看Condition接口文档,可以知道此接口替代了Object中的wait(),notify(),notyfyAll()方法,将这些监视器方法进行封装,变成了Condition监视器对象,可以和任意锁进行组合。会看到Condition惯用方式:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock(); try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally { lock.unlock(); }
}
public Object take() throws InterruptedException {
lock.lock(); try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally { lock.unlock(); }
}
}
因此我们修改线程Thread(JAVA) 篇七 线程间通信(wait(),notify(),notifyAll())–等待唤醒机制中的代码为:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 煤炭类[同一资源]
*/
class Coal
{
private String carName;
private String weight;
boolean flag = true;
//创建锁对象
Lock lock = new ReentrantLock();
//通过锁对象创建Condition对象
Condition inputCondition = lock.newCondition();
Condition outputCondition = lock.newCondition();
public void input(String carName, String weight)
{
lock.lock();//获取锁
try
{
//当标志位为 true时,输入煤炭
if(flag)
{
this.carName = carName;
this.weight = weight;
System.out.println(carName +" ... "+weight);
flag = false;//标志位置false
outputCondition.signal();//唤醒输出线程中的一个
}
else
{//当标志位为 false时,输出煤炭,输入线程进入等待状态
try
{
inputCondition.await();//输入线程等待
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
} finally
{
lock.unlock();//释放锁
}
}
public synchronized void output(String carName, String weight)
{
lock.lock();//获取锁
try
{
//当标志位为 false时,输出煤炭
if(!flag)
{
this.carName = carName;
this.weight = weight;
System.out.println(carName +" ... "+weight);
flag = true;//标志位置为true
inputCondition.signal();//唤醒输入线程中的一个线程
}
else
{//当标志位为 true时,输入煤炭,输出线程进入等待状态
try
{
outputCondition.await();//输出线程等待
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
} finally
{
lock.unlock();//释放锁
}
}
}
/**
* 往里输送煤炭类
*/
class InputCar implements Runnable
{
Coal coal;
public InputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
coal.input("输入车", "输入10吨");
}
}
}
/**
* 往外输送煤炭类
*/
class OutputCar implements Runnable
{
Coal coal;
public OutputCar(Coal coal)
{
this.coal = coal;
}
@Override
public void run()
{
while(true)
{
coal.output( "车次-输出车", "碳重-输出车5吨吨");
}
}
}
/**
* 测试
*/
public class Test
{
public static void main(String[] args)
{
Coal coal = new Coal();
InputCar inputCar = new InputCar(coal);
OutputCar outputCar = new OutputCar(coal);
Thread thread = new Thread(inputCar);
Thread thread2 = new Thread(inputCar);
Thread thread3 = new Thread(outputCar);
Thread thread4 = new Thread(outputCar);
thread.start();
thread2.start();
thread3.start();
thread4.start();
}
}
打印结果为:
输入车 … 输入10吨
车次-输出车 … 碳重-输出车5吨吨
输入车 … 输入10吨
车次-输出车 … 碳重-输出车5吨吨
输入车 … 输入10吨
车次-输出车 … 碳重-输出车5吨吨
输入车 … 输入10吨
车次-输出车 … 碳重-输出车5吨吨
输入车 … 输入10吨
车次-输出车 … 碳重-输出车5吨吨
……
经过修改的代码弥补了notifyAll()方法的缺陷(把自己同一方的线程也唤醒了。这样会降低运行效率等)。
通过给一个锁上面加上多组监视器,用于解决notifyAll()的问题。
如下是一道面试器,关于Lock Condition的应用:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*
* 编写一个程序,开启三个线程。这三个线程的ID分别为A,B,C,每个线程将自己的ID在屏幕上打印10遍。
* 要求输出的结果必须按照顺序显示 如:ABCABCABC……依次递归
*/
public class TestABCAlternate
{
public static void main(String[] args)
{
AlternateDemo alternateDemo = new AlternateDemo();
new Thread(new Runnable()
{
@Override
public void run()
{
for (int i = 1; i <= 10; i++)
{
alternateDemo.loopA(i);
}
}
},"A").start();
new Thread(new Runnable()
{
@Override
public void run()
{
for (int i = 1; i <= 10; i++)
{
alternateDemo.loopB(i);
}
}
},"B").start();
new Thread(new Runnable()
{
@Override
public void run()
{
for (int i = 1; i <= 10; i++)
{
alternateDemo.loopC(i);
System.out.println("-----------------------------------");
}
}
},"C").start();
}
}
class AlternateDemo
{
//设置标志位
int flag = 1;
Lock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
Condition conditionC = lock.newCondition();
public void loopA(int numOfTime)
{
lock.lock();//获取锁
try
{
if(flag != 1)
{
try
{
conditionA.await();//线程A等待
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" : "+ numOfTime);
flag = 2;//标志位置2
conditionB.signal();//唤醒线程B
} finally
{
lock.unlock();//释放锁
}
}
public void loopB(int numOfTime)
{
lock.lock();//获取锁
try
{
if(flag != 2)
{
try
{
conditionB.await();//线程A等待
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" : "+ numOfTime);
flag = 3;//标志位置3
conditionC.signal();//唤醒线程C
} finally
{
lock.unlock();//释放锁
}
}
public void loopC(int numOfTime)
{
lock.lock();//获取锁
try
{
if(flag != 3)
{
try
{
conditionC.await();//线程A等待
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" : "+ numOfTime);
flag = 1;//标志位置1
conditionA.signal();//唤醒线程A
} finally
{
lock.unlock();//释放锁
}
}
}
本文探讨Java中线程间通信的高级机制,重点介绍Lock和Condition接口如何改进传统synchronized方法,实现更灵活、高效的线程同步,通过实例展示输入输出线程的正确交互及按序交替执行。
1945

被折叠的 条评论
为什么被折叠?



