似梦似意境

既然选择远方,便只顾风雨兼程

Java 线程通信

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();
         }
     }
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Luomingkui1109/article/details/79961699
上一篇Java 线程同步与死锁
下一篇Java 线程池详解
想对作者说点什么? 我来说一句

图书管理线程通信问题

2011年09月10日 8KB 下载

生产者消费者问题 Java实现

2009年01月17日 8KB 下载

没有更多推荐了,返回首页

关闭
关闭