线程的同步解决了异步访问共享数据时处理的不安全和数据不一致的问题,但是这还是远远不够的,线程之间还需要相互通信,相互通知消息以便协同完成工作。在Java中线程的通信是通过wait(),notify(),notifyAll()等方法来完成的,这些方法都是Object类的方法,在Java中每个对象内部除了有一个对象锁外还有一个等待队列,这个队列存放了所有对待这个对象锁的线程。
以生产者消费者问题为例,代码如下:
public class ThreadCommunication
{
public static void main(String[] args)
{
Queue q = new Queue();
Producer p = new Producer(q);
Consumer c = new Consumer(q);
p.start();
c.start();
}
}
class Producer extends Thread
{
Queue q;
Producer(Queue q)
{
this.q = q;
}
public void run()
{
for(int i=0;i<10;i++)
{
q.put(i);
System.out.println("Producer put "+i);
}
}
}
class Consumer extends Thread
{
Queue q;
Consumer(Queue q)
{
this.q = q;
}
public void run()
{
while(true)
{
System.out.println("comsumer get "+ q.get());
}
}
}
class Queue
{
int value = 0;
boolean isFull = false;
public synchronized void put(int v) // wait 必须在Synchronized方法或synchronized块中使用
{
if (!isFull)
{
value = v;
isFull = true;
notify();
}
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public synchronized int get() // wait 必须在Synchronized方法或synchronized块中使用
{
if (!isFull)
{
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
isFull = false;
notify();
return value;
}
}
以生产者消费者问题为例,代码如下:
public class ThreadCommunication
{
public static void main(String[] args)
{
Queue q = new Queue();
Producer p = new Producer(q);
Consumer c = new Consumer(q);
p.start();
c.start();
}
}
class Producer extends Thread
{
Queue q;
Producer(Queue q)
{
this.q = q;
}
public void run()
{
for(int i=0;i<10;i++)
{
q.put(i);
System.out.println("Producer put "+i);
}
}
}
class Consumer extends Thread
{
Queue q;
Consumer(Queue q)
{
this.q = q;
}
public void run()
{
while(true)
{
System.out.println("comsumer get "+ q.get());
}
}
}
class Queue
{
int value = 0;
boolean isFull = false;
public synchronized void put(int v) // wait 必须在Synchronized方法或synchronized块中使用
{
if (!isFull)
{
value = v;
isFull = true;
notify();
}
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public synchronized int get() // wait 必须在Synchronized方法或synchronized块中使用
{
if (!isFull)
{
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
isFull = false;
notify();
return value;
}
}