线程的概念是什么?线程之间是如何通讯的? java
线程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程原本就具备动态的含义,然而实质上是经过线程来执行体现的,从这个意义上说,Windows中进程的动态性意义已经不是很明显了,只算是给程序所占的资源划定一个范围而已,真正具备动态性意义的是线程。 多线程
其实,Java提供了3个很是重要的方法来巧妙地解决线程间的通讯问题。这3个方法分别是:wait()、notify()和notifyAll()。它们都是Object类的最终方法,所以每个类都默认拥有它们。 dom
虽然全部的类都默认拥有这3个方法,可是只有在synchronized关键字做用的范围内,而且是同一个同步问题中搭配使用这3个方法时才有实际的意义。 this
这些方法在Object类中声明的语法格式以下所示: spa
final void wait() throws InterruptedExceptionfinal void notify()final void notifyAll() 线程
其中,调用wait()方法可使调用该方法的线程释放共享资源的锁,而后从运行态退出,进入等待队列,直到被再次唤醒。而调用notify()方法能够唤醒等待队列中第一个等待同一共享资源的线程,并使该线程退出等待队列,进入可运行态。调用notifyAll()方法可使全部正在等待队列中等待同一共享资源的线程从等待状态退出,进入可运行状态,此时,优先级最高的那个线程最早执行。显然,利用这些方法就没必要再循环检测共享资源的状态,而是在须要的时候直接唤醒等待队列中的线程就能够了。这样不但节省了宝贵的CPU资源,也提升了程序的效率。 队列
因为wait()方法在声明的时候被声明为抛出InterruptedException异常,所以,在调用wait()方法时,须要将它放入try…catch代码块中。此外,使用该方法时还须要把它放到一个同步代码段中,不然会出现以下异常: 进程
"java.lang.IllegalMonitorStateException: current thread not owner" 资源
这些方法是否是就能够实现线程间的通讯了呢?下面将经过多线程同步的模型:生产者和消费者问题来讲明怎样经过程序解决多线程间的通讯问题。 get
案例:线程的通讯
案例说明
下面这个程序演示了多个线程之间进行通讯的具体实现过程。程序中用到了4个类,其中ShareData类用来定义共享数据和同步方法。在同步方法中调用了wait()方法和notify()方法,并经过一个信号量来实现线程间的消息传递。
实现过程
//CommunicationDemo.java 描述:生产者和消费者之间的消息传递过程
class ShareData{
private char c;
private boolean isProduced = false; // 信号量
public synchronized void putShareChar(char c) // 同步方法putShareChar()
{
if (isProduced){ // 若是产品还未消费,则生产者等待
try{
wait(); // 生产者等待
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.c = c;
isProduced = true; // 标记已经生产
notify(); // 通知消费者已经生产,能够消费
}
public synchronized char getShareChar() // 同步方法getShareChar()
{
if (!isProduced) // 若是产品还未生产,则消费者等待
{
try{
wait(); // 消费者等待
}catch(InterruptedException e){
e.printStackTrace();
}
}
isProduced = false; // 标记已经消费
notify(); // 通知须要生产
return this.c;
}
}
class Producer extends Thread // 生产者线程
{
private ShareData s;
Producer(ShareData s){
this.s = s;
}
public void run(){
for (char ch = ''A''; ch <= ''D''; ch++){
try{
Thread.sleep((int)(Math.random()*3000));
}catch(InterruptedException e){
e.printStackTrace();
}
s.putShareChar(ch); // 将产品放入仓库
System.out.println(ch + " is produced by Producer.");
}
}
}
class Consumer extends Thread // 消费者线程
{
private ShareData s;
Consumer(ShareData s){
this.s = s;
}
public void run(){
char ch;
do{
try{
Thread.sleep((int)(Math.random()*3000));
}catch(InterruptedException e){
e.printStackTrace();
}
ch = s.getShareChar(); // 从仓库中取出产品
System.out.println(ch + " is consumed by Consumer. ");
}while (ch != ''D'');
}
}
class CommunicationDemo{
public static void main(String[] args){
ShareData s = new ShareData();
new Consumer(s).start();
new Producer(s).start();
}
}