java中线程通信(传统的线程通信)

假设现在系统有两个线程,这两个线程分别代表存款者和取钱者——现在假设系统有一种特殊的要求,系统要求存款者和取钱者不断地重复存款、取钱的动作。而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱。不允许存款者连续两次存钱,也不允许取钱者连续两次取钱。

为了实现这种功能,可以借助Object类提供的wait()、notify()、notifyAll() 3 个方法,这3个方法并不属于Thread类,而是属于Object类。但这3 个方法必须由同步监视器对象来调用,这可分以下两种情况:

1、对于使用synchronized修饰的同步方法,因为该类的默认实例是(this)就是同步监视器。所以可以在同步方法中直接调用这3个方法。

2、对于使用synchronized修饰的同步代码块,同步监视器是synchronized后括号里的对象,所以必须使用该对象调用这3个方法。

关于这3个方法的解释如下:

wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒该线程。该wait()方法有三种形式——无时间参数的wait(一直等待,知道其他线程通知),带毫秒参数的wait和带毫秒、毫微妙参数的wait(这两种方法都是等待指定时间后自动苏醒) 调用wait方法的当前线程会释放对该同步监视器的锁定。

notify():唤醒在次同步监视器上等待的单个线程。如果所有的线程都在此同步监视器上等待,则会选择唤醒其中一个线程。选择是任意的。只有当前线程放弃对该同步监视器的锁定后(使用wait方法),才可以执行被唤醒的线程。

notifyAll():唤醒在此同步监视器上等待的所有线程。只有当前线程放弃对同步监视器的锁定后,才可以执行被唤醒的线程。

 1 public class DrawTest{
 2     public static void main(String[] args){
 3         Account a=new Account("刘腾",10000);
 4         new DrawThread(a,100).start();
 5         new InThread(a,50).start();
 6         new InThread(a,60).start();
 7         new InThread(a,70).start();
 8     }
 9 }
10 //账户类
11 class Account{
12     private String name;
13     private double money;
14     private boolean flag=false;
15
16     public Account(){}
17     public Account(String name,double money){
18         this.name=name;
19         this.money=money;
20     }
21     public double getMoney(){
22         return money;
23     }
24     public synchronized void draw(double drawmoney){
25             try{
26             //如果flag为假,说明还没有人往里面存钱,所以让该线程等待。
27                 if(!flag){
28                     wait();
29                 }else{
30                     System.out.println("取出钱数为:"+drawmoney+" 剩余钱数:"+(getMoney()-drawmoney));
31                     flag=false;
32                     notifyAll();
33                 }
34             }catch(Exception e){System.out.println(e);}
35         }
36     public synchronized void deposit(double inmoney){
37         try{
38             if(!flag){
39                 System.out.println("存入钱数为:"+inmoney+" 目前的钱数为:"+(getMoney()+inmoney));
40                 flag=true;
41                 notifyAll();
42             }else{
43                 wait();
44             }
45         }catch(Exception e){}
46     }
47 }
48 //取钱线程
49 class DrawThread extends Thread{
50     private Account account;
51     private double drawmoney;
52
53     public DrawThread (Account account,double drawmoney){
54         this.account=account;
55         this.drawmoney=drawmoney;
56     }
57     public void run(){
58         for(int i=0;i<100;i++){
59             account.draw(drawmoney);
60         }
61     }
62 }
63 class InThread extends Thread{
64     private Account account;
65     private double inmoney;
66
67     public InThread(Account account,double inmoney){
68         this.account=account;
69         this.inmoney=inmoney;
70     }
71     public void run(){
72         for(int k=0;k<100;k++){
73             account.deposit(inmoney);
74         }
75     }
76 }
时间: 2024-12-28 05:09:10

java中线程通信(传统的线程通信)的相关文章

Java 中几种常用的线程池

Java 中几种常用的线程池 转载 : https://www.cnblogs.com/sachen/p/7401959.html 原创 2016年04月14日 23:29:01 标签: java / 线程池 / Executor 878 概述: 在java内置API中操作线程所用到的类为Thread.创建线程一般有两种方式, 继承Thread方式 实现Runnable方式,并以runnable作为target创建Thread 在Android中的耗时任务一般都需要另开线程来执行,常常需要用线程

在java中怎样实现多线程?线程的4种状态

一.在java中怎样实现多线程? extends Thread implement Runnable 方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可. 下面是一个例子: public class MyThread extends Thread { int count= 1, number; public MyThread(int num) { number = num; System.out.printl

Java中常用的四种线程池

在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解.不过,在Executors类中,为我们提供了常用线程池的创建方法.接下来我们就来了解常用的四种: newFixedThreadPool 首先,看一下这种线程池的创建方法: public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExec

简谈Java中常用的四种线程池

newFixedThreadPool 首先,看一下这种线程池的创建方法: public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } 从构造方法可以看出,它创建了一个固定大小的线程池,每次提交一

Java多线程有哪几种实现方式? Java中的类如何保证线程安全? 请说明ThreadLocal的用法和适用场景

java的同步机制,大概是通过:1.synchronized:2.Object方法中的wait,notify:3.ThreadLocal机制来实现的, 其中synchronized有两种用法:1.对类的方法进行修饰2.synchronized(对象)的方法进行修饰 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量.这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大.

Java中ThreadLocal无锁化线程封闭实现原理

虽然现在可以说很多程序员会用ThreadLocal,但是我相信大多数程序员还不知道ThreadLocal,而使用ThreadLocal的程序员大多只是知道其然而不知其所以然,因此,使用ThreadLocal的程序员很多时候会被它导入到陷进中去,其实java很多高级机制系列的很多东西都是一把双刃剑,也就是有利必有其弊,那么我们的方法是找到利和弊的中间平衡点,最佳的方式去解决问题. 本文首先说明ThreadLocal能做什么,然后根据功能为什么要用它,如何使用它,最后通过内部说明讲解他的坑在哪里,使

java中如何选择Collection Class--java线程(第3版)

使用哪一个collection是最好的?很明显,没有单一的答案可以适合所有的状态.无论如何,以下还是有一些通用的建议.遵循这些建议,我们就可以缩小collection的选择范围. 使用collection class 的时候,通过接口来运用. 如同所有的java程序设计,接口可以隔离开实现的细节.通过使用接口,程序设计师可以轻易地只以修改初始程序代码就将程序重构成使用不同collection的实现. 使用没有被同步化过的collection会有小小的性能提升. 这可能会让许多开发者吃惊---要了

java中的并发:进程和线程

1.简介 1)进程:同一个系统中执行的一个子程序,包含三部分:虚拟CPU,代码,数据. 2)线程:同一个进程中执行的子程序流. 3)进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能.一个进程虽然包括多个线程,但是这些线程是共同享有进程占有的资源和地址空间的.进程是操作系统进行资源分配的基本单位,而线程是操作系统进行调度的基本单位. 2.创建一个进程 2.1首先了解三个类    1)Process(抽象类)       进程类,提供了执行从进程输入.执行输出到进程.等待进程完成.检查

Android java 中如何优雅的结束线程

线程对象属于一次性消耗品,一般线程执行完run方法之后,线程就正常结束了,线程结束之后就报废了,不能再次start,只能新建一个线程对象.但有时run方法是永远不会结束的.例如在程序中使用线程进行Socket监听请求,或是其他的需要循环处理的任务.在这种情况下,一般是将这些任务放在一个循环中,如while循环.当需要结束线程时,如何退出线程呢? 有三种方法可以结束线程: 1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止 2. 使用interrupt()方法中断线程 3. 使用

Java中程序、进程、线程的区别。

程序.进程.线程的区别. 程序(program):是一个指令的集合.程序不能独立执行,只有被加载到内存中,系统为他分配资源后才能执行. 进程(process):一个执行中的程序称为进程. 进程是系统分配资源的独立单位,每个进程战友特定的地址空间. 程序是进程的静态文本描述.进程是程序在系统内顺序执行的动态活动. 线程(thread):是进程的"单一的连续控制流程". 线程是CPU调度和分配的基本单位,是比进程更小的能独立运行的基本单位,也被称为轻量级的进程. 线程不能独立存在,必须依附