根据问题的描述,我将问题用以下代码演示,ThreadA、ThreadB、ThreadC,ThreadA 用于初始化数据 num,
只有当num初始化完成之后再让ThreadB和ThreadC获取到初始化后的变量num。
分析过程如下:
考虑到多线程的不确定性,因此我们不能确保ThreadA就一定先于ThreadB和ThreadC前执行,就算ThreadA
先执行了,我们也无法保证ThreadA什么时候才能将变量num给初始化完成。因此我们必须让ThreadB和ThreadC
去等待ThreadA完成任何后发出的消息。
现在需要解决两个难题,一是让 ThreadB 和 ThreadC 等待 ThreadA 先执行完,二是 ThreadA 执行完之后给
ThreadB和ThreadC发送消息。
使用Java API的Semaphore类来控制线程的等待和释放
public class ThreadCommunication {
private static int num;
/**
* 定义一个信号量,该类内部维持了多个线程锁,可以阻塞多个线程,释放多个线程,
. 线程的阻塞和释放是通过 permit 概念来实现的
* 线程通过 semaphore.acquire()方法获取 permit,如果当前 semaphore 有 permit 则分配给该线程,
如果没有则阻塞该线程直到 semaphore
* 调用 release()方法释放 permit。
* 构造函数中参数:permit(允许) 个数
*/
//声明一个semaphore对象
private static Semaphore semaphore = new Semaphore(0);
public static void main(String[] args)
{
Thread threadA = new Thread(new Runnable(){
@Override
public void run(){
try
{
//模拟操作之后初始化变量num
Thread.sleep(1000);
num=1;
//释放2个permit
semaphore.release(2);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
Thread threadB = new Thread(new Runnable(){
@Override
public void run(){
try
{
//获取permit,如果semaphore没有可用permit,则等待,否则消耗一个
semaphore.acquire();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取到num值为:"+num);
}
});
Thread threadC = new Thread(new Runnable(){
@Override
public void run(){
try
{
//获取permit,如果semaphore没有可用permit,则等待,否则消耗一个
semaphore.acquire();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"获取到的num值为:"+num);
}
});
//同时开启3个线程
threadA.start();
threadB.start();
threadC.start();
}
}
网友评论