精华内容
下载资源
问答
  • Java多线程间通信

    千次阅读 2019-10-25 22:23:09
    这对于 多线程之间的协作不是很友好。 线程间的通信就是为了线程之间更加友好的协作。 线程间通信 如果线程之间不能通信,A线程为了判断B线程的运行状态就必须轮询的去监听,但是轮询存在两个大问题: 信息获取不...

    Java中的多线程共享的是堆内存,栈内存是线程私有的,A线程无法获取B线程的运行情况。
    这对于 多线程之间的协作不是很友好。

    线程间的通信就是为了线程之间更加友好的协作。

    线程间通信

    如果线程之间不能通信,A线程为了判断B线程的运行状态就必须轮询的去监听,但是轮询存在两个大问题:

    • 信息获取不及时。
    • 浪费CPU的资源。

    wait

    wait方法来自Object类,被final修饰,意味着子类不能重写。

    public final void wait() throws InterruptedException {
        wait(0);
    }
    

    当调用wait()方法后,当前线程会 释放锁,让出CPU的执行权,进入“等待”状态,等待被其他线程唤醒。

    默认:如果没有线程唤醒,会一直等待,除非加“等待超时时间”。

    使用的条件

    • synchronized修饰的同步方法
    • synchronized同步代码块

    调用wait的前提是必须先获得锁,否则会抛出 IllegalMonitorStateException 异常。

    notify/notifyAll

    notify/notifyAll 会通知此对象的监视器等待的线程唤醒并接入。

    区别是:notify通知一个,notifyAll通知所有。

    生产者消费者-例子

    故事情景

    有一个工厂类 Factory,记录着 工厂的最大库存数和当前库存数。
    有一个生产者类 Producer,负责商品的生产,一旦有了库存就要通知消费者消费,一旦库存满了就不能继续生产了。
    有一个消费者类 Consumer,负责商品的消费,有库存时就会消费,无库存时就要等待。

    反面例子

    当我们不使用wait/notify时,就必须轮询去监听工厂的库存,代码如下:

    Factory
    @Data
    public class Factory {
    	//库存总数
    	public final static int MAX = 100;
    	//当前数量
    	private int count = 0;
    
    	public synchronized void produce(){
    		SleepUtil.sleep(50);
    		count++;
    		System.out.println("生产者生产:"+count);
    	}
    
    	public synchronized void consume(){
    		SleepUtil.sleep(100);
    		count--;
    		System.out.println("消费者消费:"+count);
    	}
    }
    
    Producer
    public class Producer extends Thread {
    	private Factory factory;
    
    	public Producer(Factory factory) {
    		this.factory = factory;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			//每秒查询一次库存,未满则生产。
    			if (factory.getCount() < Factory.MAX) {
    				factory.produce();
    			}else {
    				SleepUtil.sleep(1000);
    			}
    		}
    	}
    }
    
    Consumer
    public class Consumer extends Thread {
    	private Factory factory;
    
    	public Consumer(Factory factory) {
    		this.factory = factory;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			//每秒查询一次库存,有则消费。
    			if (factory.getCount() > 0) {
    				factory.consume();
    			}else {
    				SleepUtil.sleep(1000);
    			}
    		}
    	}
    }
    
    Client
    public class Client {
    	public static void main(String[] args) {
    		Factory factory = new Factory();
    		new Producer(factory).start();
    		new Consumer(factory).start();
    	}
    }
    

    轮询的间隔为1秒,信息会获取不及时,即使没有消费者消费,生产者仍然会监听,浪费CPU的资源。

    正面例子

    Factory 和 Client 代码不变,修改 Producer 和 Consumer。

    Producer
    public class Producer extends Thread {
    	private Factory factory;
    
    	public Producer(Factory factory) {
    		this.factory = factory;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			synchronized (factory){
    				if (factory.getCount() >= Factory.MAX) {
    					try {
    						//库存足够 等待消费
    						factory.wait();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				factory.produce();
    				//通知消费者消费
    				factory.notifyAll();
    			}
    		}
    	}
    }
    
    Consumer
    public class Consumer extends Thread {
    	private Factory factory;
    
    	public Consumer(Factory factory) {
    		this.factory = factory;
    	}
    
    	@Override
    	public void run() {
    		while (true) {
    			synchronized (factory){
    				if (factory.getCount() <= 0) {
    					try {
    						//没有库存 等待生产
    						factory.wait();
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
    				factory.consume();
    				factory.notifyAll();
    			}
    		}
    	}
    }
    

    库存一满,生产者就会wait,只要没人消费,会一直wait,不会浪费CPU的资源。
    只要一生产商品,就会通知消费者来消费,解决了信息获取不及时的问题。

    展开全文
  • 在多线程的编码实现中,往往每个线程之间是相互协作实现的,或者说是有先后顺序的,多线程之间通信能够避免对同一共享变量的争夺。 一、wait()和 notify()1. wait()方法使得当前线程必须要等待,等到另外一个...
    在多线程的编码实现中,往往每个线程之间是相互协作实现的,或者说是有先后顺序的,多线程之间的通信能够避免对同一共享变量的争夺。
    

    一、wait()和 notify()

    1. wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。
    
      当前的线程必须拥有当前对象的monitor,也即lock,就是锁。 
      
      线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。
      
      要确保调用wait()方法的时候拥有锁,即,wait()方法的调用必须放在synchronized方法或synchronized块中。
        
      一个小比较:
      当线程调用了wait()方法时,它会释放掉对象的锁。
      
      另一个会导致线程暂停的方法:Thread.sleep(),它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。
    
    
    2. notify()方法会唤醒一个等待当前对象的锁的线程。
    
      如果多个线程在等待,它们中的一个将会选择被唤醒。这种选择是随意的,和具体实现有关。(线程等待一个对象的锁是由于调用了wait方法中的一个)。
    
      **被唤醒的线程是不能被执行的,需要等到当前线程放弃这个对象的锁。**
    
      被唤醒的线程将和其他线程以通常的方式进行竞争,来获得对象的锁。也就是说,被唤醒的线程并没有什么优先权,也没有什么劣势,对象的下一个线程还是需要通过一般性的竞争。
    
        和 wait()方法一样,notify方法调用必须放在synchronized方法或synchronized块中。
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MyList {
    
        private static List<String> list = new ArrayList<String>();
    
        public static void add() {
            list.add("anyString");
        }
    
        public static int size() {
            return list.size();
        }
    }
    
    
    public class ThreadA extends Thread {
    
        private Object lock;
    
        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                synchronized (lock) {
                    if (MyList.size() != 5) {
                        System.out.println("wait begin "
                                + System.currentTimeMillis());
                        lock.wait();
                        System.out.println("wait end  "
                                + System.currentTimeMillis());
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    public class ThreadB extends Thread {
        private Object lock;
    
        public ThreadB(Object lock) {
            super();
            this.lock = lock;
        }
    
        @Override
        public void run() {
            try {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++) {
                        MyList.add();
                        if (MyList.size() == 5) {
                            lock.notify();
                            System.out.println("已经发出了通知");
                        }
                        System.out.println("添加了" + (i + 1) + "个元素!");
                        Thread.sleep(1000);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class Run {
    
        public static void main(String[] args) {
    
            try {
                Object lock = new Object();
    
                ThreadA a = new ThreadA(lock);
                a.start();
    
                Thread.sleep(50);
    
                ThreadB b = new ThreadB(lock);
                b.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    线程A要等待某个条件满足时(list.size()==5),才执行操作。线程B则向list中添加元素,改变list 的size。
    
    A,B之间如何通信的呢?也就是说,线程A如何知道 list.size() 已经为5了呢?
    
    这里用到了Object类的 wait() 和 notify() 方法。
    
    当条件未满足时(list.size() !=5),线程A调用wait() 放弃CPU,并进入阻塞状态。
    
    当条件满足时,线程B调用 notify()通知 线程A,所谓通知线程A,就是唤醒线程A,并让它进入可运行状态。
    

    二、synchronized 关键字

    public class MyObject {
    
        synchronized public void methodA() {
            //do something....
        }
    
        synchronized public void methodB() {
            //do some other thing
        }
    }
    
    public class ThreadA extends Thread {
    
        private MyObject object;
    //省略构造方法
        @Override
        public void run() {
            super.run();
            object.methodA();
        }
    }
    
    public class ThreadB extends Thread {
    
        private MyObject object;
    //省略构造方法
        @Override
        public void run() {
            super.run();
            object.methodB();
        }
    }
    
    public class Run {
        public static void main(String[] args) {
            MyObject object = new MyObject();
    
            //线程A与线程B 持有的是同一个对象:object
            ThreadA a = new ThreadA(object);
            ThreadB b = new ThreadB(object);
            a.start();
            b.start();
        }
    }
    由于线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是它们是同步执行的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。这样,线程A和线程B就实现了通信。
    
    这种方式,本质上就是“共享内存”式的通信。多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。
    
    展开全文
  • Java多线程之间通信

    2017-07-22 14:12:20
    多线程之间通信详解

     

    Java中线程间通信

    1.      线程间通信(通讯): 多个线程在处理同一个资源,但任务不同。

    一、等待/唤醒机制

    1.  涉及的方法:

    (1) wait(); 使线程处于冻结状态,被wait的线程会存储到线程池(等待集)中;

    (2) notify(); 唤醒线程池中的一个线程,这个线程是任意的;

    (3) notifyAll(); 唤醒线程池中的所有线程。

    2.  这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法;而且必须要明确到底操作的是哪个锁上的线程。即必须明确线程由那个监视器监视。

    3.  监视器: 就是所说的锁。

    4. 为什么操作线程的方法wait()、notify()、notifyAll()定义在了Object类中?

    答:因为这些方法就是监视器的方法,监视器就是锁,锁可以是任意的对象,如Object obj = new Object();既然可以是任意对象,那么这些方法需要定义在最高的类中,即定义在Object类中。

    5、管道通信

    6、内存共享

    展开全文
  • 多线程——4线程通信

    千次阅读 2019-11-25 22:35:35
    多线程——4线程通信 一、内容安排 wait和notify方法 简单的生产者消费者 面试点 二、文章内容 1. wait和notify方法 ​ 当一个对象调用了wait方法那么它将阻塞当前线程, 直到有另外一个线程调用了...

    多线程——4线程间的通信

    一、内容安排

    1. wait和notify方法
    2. 简单的生产者消费者
    3. 面试点

    二、文章内容

    1. wait和notify方法

    ​ 当一个对象调用了wait方法那么它将阻塞当前线程, 直到有另外一个线程调用了当前对象的notify方法,被阻塞的线程才可能被唤醒。

    注意: 若要调用这两个方法必须先获得对象的锁,不让会抛出异常

    • 案列: 启动A、B两个线程,A线程中调用wait方法在wait之后打印”被唤醒“; 在B线程中先打印”我来唤醒“,然后调用notify方法
    public static void main(String[] args) {
            //定义公用对象
            Object object = new Object();
    
            //线程A
            new Thread(()->{
    
                synchronized (object) {
                    try {
                        //调用object的wait方法阻塞当前线程
                        object.wait();
                        //打印
                        System.out.println("我被唤醒了");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    
            //线程B
            new Thread(()->{
                System.out.println("我要唤醒A线程");
                synchronized (object) {
                    try {
                        TimeUnit.SECONDS.sleep(3);
                        object.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
    
        }
    

    2.简单的生产者消费者

    有了上面提到的wait和notify两个方法,我们可以利用这两个方法实现一个简单(生产者生产一个等待消费者消费再生产)的生产者消费者;

    实现思路:

    1. 开启两个线程,一个不断的生产一个不断的消费
    2. 生产者线程生产消息之后唤醒等待中的消费者并让自己阻塞,等待消费者消费之后让消费者唤醒自己
    3. 消费者线程: 消费消息,唤醒生产者线程,然后自己阻塞

    具体实现:

    public class ProducerConsumer {
    
        static Object LOCK = new Object();
        static Boolean isProduced = false;
        static Integer i = 0;
    
        public static void main(String[] args) {
    
            // 定义生产者线程
            new Thread(() -> {
                while (true) {
                    synchronized (LOCK) {
                        if (!isProduced) {
                            System.out.println("生产者生产消息" + ++i);
                            LOCK.notify();
                            isProduced = true;
                        } else {
                            try {
                                LOCK.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }, "producer").start();
    
    
            // 定义消费者线程
            new Thread(() -> {
                while (true) {
                    synchronized (LOCK) {
                        if (isProduced) {
                            System.out.println("消费者生产消息" + i);
                            LOCK.notify();
                            isProduced = false;
                        } else {
                            try {
                                LOCK.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }, "consumer").start();
    
    
        }
    }
    
    

    3.面试考点

    • wait和sleep的区别
      1. 所属对象不同: wait是Object中的方法, sleep是Thread中的方法
      2. sleep不会释放锁,而wait会释放锁
      3. sleep可以直接使用在任何地方, 但是使用wait方法必须使用在同步带吗块儿中;并且需要使用锁对象
      4. sleep自动唤醒, wait需要别人唤醒

    展开全文
  • 多线程间通信和同步

    千次阅读 2019-06-15 11:21:07
    最近看了很多关于网络编程和多线程的...三、线程之间如何通信 四、线程安全 五、线程的同步 (一)互斥量mutex (二)临界区 critical section (三)信号量 semaphore (四)事件 event 一、什么是多线程? ...
  • 多进程和多线程之间通信方式及通信实现步骤小结
  • JAVA多线程之线程通信方式

    千次阅读 2019-06-18 16:21:52
    本总结我对于JAVA多线程线程之间通信方式的理解,主要以代码结合文字的方式来讨论线程通信,故摘抄了书中的一些示例代码。 二,线程通信方式 ①同步 这里讲的同步是指多个线程通过synchronized...
  • iOS开发多线程-线程通信

    千次阅读 2015-11-24 23:25:51
     线程间通信:在1个进程中,线程往往不是孤立存在的,线程之间需要经常进行通信    线程间通信的体现  1个线程传递数据给另1个线程  在1个线程中执行完特定任务后,转到另1个线程继续执行任务    线程...
  • 上一章节讲了wait/notify通信,这一节我们来探讨使用管道进行通信。 java中提供了IO流使我们很方便的对数据进行操作,pipeStream是一种...java中提供了四个类使得线程间可以通信: 字节流:PipeInputStream,PipedOu
  • * 当个线程对于同一个资源进行处理时,且处理方式相同,那么线程之间不需要通信。 * * 线程通信发生在个线程在处理同一个资源,但是处理的动作(任务)却不相同。 * * */ //资源类 class ...
  • Java 多线程间通信及线程安全

    千次阅读 2018-05-16 16:57:27
    多线程间通信的意义    java中使用多线程操作同一数据时,需要考虑到线程间的通讯,否则会出现数据错误,程序死锁卡死的情况。所以多线程在操作同一数据时必须考虑其先后顺序以保证数据准确,且不会出现死锁的...
  • 操作系统的主要任务是管理计算机的软件、硬件资源。现代操作系统的主要特点是用户和任务,也就是程序的并行执行,...而线程间通信又和进程间的通信不同。由于进程的数据空间相对独立而线程是共享数据空间的,
  • Java多线程之间通信

    千次阅读 2021-06-11 09:39:01
    * 线程之间通讯问题 等待唤醒,通知唤醒 * 线程交替执行 A B操作同一个变量 * A+1 * B-1 */ public class A { public static void main(String[] args) { Data data = new Data(); //A线程执行 new Thread(()...
  •  这次主要是使用nanomsg库实现多线程之间通信,在我们复杂的多线程编程中可能各个线程需要共用一些信息,平常加互斥锁等等,有时候也是相当麻烦,这里是使用nanomsg库实现多线程的通信,主要这次是一对一线程双向...
  • 多线程-线程之间通信

    千次阅读 2019-03-23 09:24:02
    我们经常说线程之间通信,线程之间的协作,但是根据他的应用场景其实是很容易搞...这种相互等待的过程,就是线程之间通信的过程,也就是协作的过程,那么从以下两个角度或者更的角度去解决这个问题,并且说明一些关...
  • MFC VC++多线程间通信

    千次阅读 2016-04-15 15:35:09
    线程通信 1.线程之间通信简介 一般而言,在一个应用程序中(即...这种线程通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的。线程通信涉及到4个问题: (1) 线程如何传递信息
  • 线程间通信:在1个进程中,线程往往不是孤立存在的,线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法 ...
  •  线程间通信:在1个进程中,线程往往不是孤立存在的,线程之间需要经常进行通信    线程间通信的体现  1个线程传递数据给另1个线程  在1个线程中执行完特定任务后,转到另1个线程继续执行任务    
  • Python 多线程及线程间通信

    千次阅读 2020-09-05 17:27:00
    作者:billy 版权声明:著作权归作者所有,...由于线程是操作系统直接支持的执行单元,因此,高级语言(如 Python、Java 等)通常都内置多线程的支持。Python 的标准库提供了两个模块:_thread 和 threading,_thread
  • 你和你的朋友共同完成一个任务,你们随时交流对方的工作进度,因为有些任务是要对等待对方先完成再做,这个过程就是线程通信
  • 多线程之间如何通讯 wait、notify、notifyAll()方法 lock 停止线程 多线程之间如何实现通讯 什么是多线程之间通讯? 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。 画图演示 需求:第一个...
  • 线程间通信:在1个进程中,线程往往不是孤立存在的,线程之间需要经常进行通信线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务线程间通信常用方法- ...
  • Linux多线程编程与线程间通信机制

    千次阅读 2016-01-26 17:04:44
    Linux中多线程编程技术被广泛使用,这主要是因为多线程可以提升程序的运行效率和便利性。在现在的比较大一点的linux...本文就来讲讲linux中多线程编程的实现,以及利用消息队列进行线程间通信。   一、线程的创建
  • MFC 多线程间通信

    万次阅读 多人点赞 2014-05-08 19:40:41
    线程之间通信简介全局变量方式参数传递方式消息传递方式线程同步法 线程通信 1.线程之间通信简介 一般而言,在一个应用程序中(即进程),一个线程往往不是孤立存在的,常常需要和其它线程通信,...
  • Java进阶知识 - 多线程与线程间通信

    千次阅读 2019-03-12 19:21:31
    但在某些复杂的情况下, 需要使用线程来协同完成某个任务, 这就涉及到线程间通信(inter-thread communication)的问题了. 主要涉及的内容有: thread.join() 方法 object.wait() 方法 object.notif...
  • 多线程线程间通信的三种方法

    千次阅读 2012-09-13 11:39:18
    多线程通信的方法主要有以下三种:  1.全局变量 进程中的线程内存共享,这是比较常用的通信方式和交互方式。 注:定义全局变量时最好使用volatile来定义,以防编译器对此变量进行优化。   2.Message消息...
  • 多线程专题之线程通信

    千次阅读 2008-02-23 11:56:00
    接上一回 - 多线程专题之MFC线程(2),我们来聊聊线程通信:/*------------------------------------------------------------*/ 多线程间通信应用程序中多线程的使用通常都是用于主线程执行与用户交互,次要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 325,656
精华内容 130,262
关键字:

多线程之间是怎么通信的