Java 线程通信

45人阅读 评论(0) 收藏 举报
分类:
1.线程通信
    线程通信(线程交互):当多个线程在完成某些任务时,多个线程之间需要一定的通信,即线程通信。
    在Object类中有两个方法:
wait() :  使当前同步监视器上的线程进入等待状态,同时释放锁
notify() / notifyAll() :  唤醒当前同步监视器上等待状态的一个(所有)线程。
    说明:以上方法只有在synchronized方法或synchronized代码块中才能使用,否则会报java.lang.IllegalMonitorStateException异常

2.实例1:
    使用两个线程打印 1-100. 线程1, 线程2 交替打印
方法一:
/*
 * 使用两个线程打印 1-100. 线程1, 线程2 交替打印
 */
public class TestWaitNotify {
     public static void main(String[] args) {
         HelloThread ht = new HelloThread();
         new Thread(ht).start();
         new Thread(ht).start();
     }
}
public class HelloThread implements Runnable{
     int i = 0;
     @Override
     public void run() {
         while(true){

              synchronized (this) {

                  notify();

                  if(i <= 100){
                       System.out.println(Thread.currentThread().getName() + ":" + i++);
                  }

                  try {
                       wait();
                  } catch (InterruptedException e) {
                  }
              }
         }
     }
}
方法二:
public class TestReview {
     public static void main(String[] args) {
         HelloThread ht = new HelloThread();
         new Thread(ht).start();
         new Thread(ht).start();
     }
}
public class HelloThread implements Runnable{
     int i = 0;
     Object obj = new Object();
     @Override
     public void run() {
         while(true){
              synchronized (obj) {
                  obj.notify();
                  if(i < 100){
                       System.out.println(Thread.currentThread().getName() + ":" + i++);
                  }
                  try {
                       obj.wait();
                  } catch (InterruptedException e) {
                  }
              }
         }
     }
}
3.实例2
    线程通信:模拟银行账户,用户 A 不断往该账户中存钱,最多存 10000 元。 当账户满了,需要通知用户B 取钱 用户B 不断从该账户中取钱,当余额不足时,需要通知用户A 开始存钱。
(1) Account
public class Account {

    private double balance;

    public Account() {
    }

    public Account(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    
    //取款方法
    public synchronized void withdraw(double amount){
        if(balance < amount){
            System.out.println("余额不足");
            
            try {
                wait();
            } catch (InterruptedException e) {
            }
            
        }else{
            balance -= amount;
            System.out.println(Thread.currentThread().getName() + " 成功取出 " + amount + " 余额为:" + balance);
            
            notifyAll();
        }
    }
    
    //存款方法
    public synchronized void deposit(double amount){
        if(balance + amount > 10000){
            System.out.println("账户已满");
            
            try {
                wait();
            } catch (InterruptedException e) {
            }
            
        }else{
            balance += amount;
            System.out.println(Thread.currentThread().getName() + " 成功存入" + amount + " 余额为:" + balance);
            
            notifyAll();
        }
    }

}
(2) CustomerA
public class CustomerA implements Runnable {

    private Account account;

    public CustomerA() {
    }

    public CustomerA(Account account) {
        this.account = account;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        while(true){
            
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            
            account.deposit(1000);
        }
    }

}
(3) CustomerB
public class CustomerB implements Runnable {

    private Account account;

    public CustomerB() {
    }

    public CustomerB(Account account) {
        this.account = account;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
            }
            
            account.withdraw(1000);
        }
    }

}
(4) TestAccount
public class TestAccount {
    
    public static void main(String[] args) {
        Account account = new Account();
        
        CustomerA ca = new CustomerA(account);
        CustomerB cb = new CustomerB(account);
        
        new Thread(ca).start();
        new Thread(cb).start();
    }

}
4.实例3
    其实上面就是生产者消费者问题,有可能产生数据不见,用等待唤醒机制解决。下面用具体的例题再次分析一下:
/*
 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,店员一次只能持有固定数量的产品(比如:20),
 如果生产者试图生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品了,
 店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
 这里可能出现两个问题:
 生产者比消费者快时,消费者会漏掉一些数据没有取到。
 消费者比生产者快时,消费者会取相同的数据。
 */
public class TestProduct {

     public static void main(String[] args) {
         Clerk clerk = new Clerk();

         Productor pro = new Productor(clerk);
         Customer cus = new Customer(clerk);

         new Thread(pro).start();
         new Thread(cus).start();
     }

}

//店员
class Clerk {
     //产品数量
     private int product;

     public Clerk() {
     }

     public Clerk(int product) {
         this.product = product;
     }

     public int getProduct() {
         return product;
     }

     public void setProduct(int product) {
         this.product = product;
     }

     // 添加货物
     public synchronized void addProduct() {
         if (product < 20) {
              System.out.println("生产者生产了第" + ++product + " 个产品");
              notifyAll();
         } else {
              System.out.println("货物已满!");
              try {
                  wait();
              } catch (InterruptedException e) {
              }
         }
     }

     // 卖货
     public synchronized void saleProduct() {
         if (product > 0) {
              System.out.println("消费者消费了第" + product-- + " 个产品");
              notifyAll();
         } else {
              System.out.println("缺货!");
              try {
                  wait();
              } catch (InterruptedException e) {
              }
         }
     }
}

// 生产者
class Productor implements Runnable {

     private Clerk clerk;

     public Productor() {
     }

     public Productor(Clerk clerk) {
         this.clerk = clerk;
     }

     public Clerk getClerk() {
         return clerk;
     }

     public void setClerk(Clerk clerk) {
         this.clerk = clerk;
     }

     @Override
     public void run() {
         while (true) {
              clerk.addProduct();
         }
     }

}

//消费者
class Customer implements Runnable {
     private Clerk clerk;

     public Customer() {
     }

     public Customer(Clerk clerk) {
         this.clerk = clerk;
     }

     public Clerk getClerk() {
         return clerk;
     }

     public void setClerk(Clerk clerk) {
         this.clerk = clerk;
     }

     @Override
     public void run() {
         while(true){
              clerk.saleProduct();
         }
     }
}
查看评论

图书管理线程通信问题

  • 2011年09月10日 09:09
  • 8KB
  • 下载

生产者消费者问题 Java实现

  • 2009年01月17日 17:34
  • 8KB
  • 下载

java多线程之线程间通信

1.多线程之等待与通知机制   1.1什么是等待通知机制?     在生活中,如我们去饭店,服务员拿菜单给我们点菜,然后记录完告诉厨房去做,然后服务员就处于等待状态了。然后厨师把菜做好,就通知服务...
  • ya_1249463314
  • ya_1249463314
  • 2016-09-26 15:59:17
  • 3741

【java并发】传统线程同步通信技术

先看一个问题: 有两个线程,子线程先执行10次,然后主线程执行5次,然后再切换到子线程执行10,再主线程执行5次……如此往返执行50次。   看完这个问题,很明显要用到线程间的通信了, 先分析一下...
  • eson_15
  • eson_15
  • 2016-05-29 11:50:59
  • 5642

Java 线程通信示例源代码

  • 2010年01月26日 11:56
  • 7KB
  • 下载

Java中的多线程(三)之线程间的通信

在第一篇文章中说过Java的并发模型是共享内存,所以线程间的通信也是基于这个原理实现的,在Java中,使用wait/notify/notifyAll是实现线程间通信的一种简单方式。 我们看下这三...
  • solo_sky
  • solo_sky
  • 2014-03-18 16:35:41
  • 915

多线程之同步线程通信小例子

最近在学习多线程的时候,看到这样的一个问题:有两个线程,一个是子线程,一个是主线程,子线程运行10次,接着主线程运行20次,接着子线程运行10,主线程运行20次,依次交替循环20次。刚开始看到这个问题...
  • zknxx
  • zknxx
  • 2016-11-15 23:21:38
  • 729

Thinking in Java---线程通信+三种方式实现生产者消费者问题

前面讲过线程之间的同步问题;同步问题主要是为了保证对共享资源的并发访问不会出错,主要的思想是一次只让一个线程去访问共享资源,我们是通过加锁的方法实现。但是有时候我们还需要安排几个线程的执行次序,而在系...
  • acm_lkl
  • acm_lkl
  • 2015-08-31 20:31:00
  • 1127

java线程通信的三种方式

1、传统的线程通信。     在synchronized修饰的同步方法或者修饰的同步代码块中使用Object类提供的wait(),notify()和notifyAll()3个方法进行线程通信。    ...
  • hpp1314520
  • hpp1314520
  • 2017-07-04 15:25:06
  • 447

JAVA线程间通信的几种方式

今天在群里面看到一个很有意思的面试题: “编写两个线程,一个线程打印1~25,另一个线程打印字母A~Z,打印顺序为12A34B56C……5152Z,要求使用线程间的通信。” 这是一道非常好的面试题...
  • hmiter
  • hmiter
  • 2017-03-03 10:10:59
  • 3035
    个人资料
    持之以恒
    等级:
    访问量: 9万+
    积分: 3219
    排名: 1万+
    最新评论