线程间通信
- 线程间通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。
- wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?
①这些方法存在于同步中(因为要对持有监视器(锁)的线程操作)
②使用这些方法必须要标识所属的同步的锁
③锁可以是任意对象,所以任意对象调用的方法一定定义Object类中。 - wait(),sleep()有什么区别?
wait()释放资源,释放锁
sleep()释放资源,不释放锁
class Res{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if(flag)
try{this.wait();}catch(Exception e){}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void out(){
if(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(name+"......"+sex);
flag=false;
this.notify();
}
}
class Input implements Runnable{
private Res r;
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while (true){
if(x==0)
r.set("Li","man");
else
r.set("李","女");
x=(x+1)%2;
}
}
}
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
public void run(){
while(true)
r.out();
}
}
class Demo{
public static void main(String[] args) {
Res r=new Res();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
线程间通信——生产者和消费者
- 对于多个生产者和消费者,为什么要定义while判断标记?
原因:让被唤醒的线程再一次判断标记 - 为什么定义notifyAll?
①因为需要唤醒对方线程
②因为只用notify,容易出现只唤醒本方现成的情况,导致程序中的所有线程都等待
class Demo{
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t1=new Thread(pro);
Thread t2=new Thread(pro);
Thread t3=new Thread(con);
Thread t4=new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void set(String name){
while(flag)
try{this.wait();}catch(Exception e){}
this.name=name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"-生产者-"+this.name);
flag=true;
this.notifyAll();
}
public synchronized void out(){
while(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"---消费者---"+this.name);
flag=false;
this.notifyAll();
}
}
class Producer implements Runnable{
private Resource res;
Producer(Resource res){
this.res=res;
}
public void run(){
while(true)
res.set("商品");
}
}
class Consumer implements Runnable{
private Resource res;
Consumer(Resource res){
this.res=res;
}
public void run(){
while(true)
res.out();
}
}
JDK1.5之后提供了多线程升级解决方案
- 将同步(synchronized)替换成Lock操作。
将Object中的wait(),notify(),notifyAll(),替换成了Condition对象
该对象可以通过Lock锁进行获取。
该示例中,对上方代码进行了优化,实现了本方只唤醒对方操作
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Demo{
public static void main(String[] args) {
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
Thread t1=new Thread(pro);
Thread t2=new Thread(pro);
Thread t3=new Thread(con);
Thread t4=new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource{
private String name;
private int count=1;
private boolean flag=false;
private Lock lock=new ReentrantLock();
private Condition con_pro=lock.newCondition();
private Condition con_con=lock.newCondition();
public void set(String name)throws InterruptedException{
lock.lock();
try {
while (flag)
con_pro.await();
this.name = name + "--" + count++;
System.out.println(Thread.currentThread().getName() + "-生产者-" + this.name);
flag = true;
con_con.signalAll();
}
finally {
lock.unlock();
}
}
public void out()throws InterruptedException{
lock.lock();
try{
while(!flag)
con_con.await();
System.out.println(Thread.currentThread().getName()+"---消费者---"+this.name);
flag=false;
con_pro.signalAll();
}
finally {
lock.unlock();
}
}
}
class Producer implements Runnable{
private Resource res;
Producer(Resource res){
this.res=res;
}
public void run(){
while(true)
try{
res.set("商品");
}
catch(InterruptedException e){}
}
}
class Consumer implements Runnable{
private Resource res;
Consumer(Resource res){
this.res=res;
}
public void run(){
while(true)
try{
res.out();
}
catch(InterruptedException e){}
}
}