多线程之间的通信
2017-04-25 22:52
120 查看
一,概述
1.什么时候需要线程间通信?* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的。
* 如果我们希望线程间有规律的切换, 就需要进行线程间通信。例如先让线程一执行,然后让线程一和线程二轮流交替执行。
2.怎么实现线程间通信?
实现线程间通信要借助于多线程同步,所以也分为两种方法,一种使用synchronized 关键字实现,另一种使用ReentrantLock 类实现。
二,使用synchronized 关键字实现线程间通信
重要点如下:* 如果希望线程等待, 就调用wait()方法。
* 如果希望唤醒等待的线程, 就调用notify()方法。
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用。
代码示例如下:
首先声明两个成员方法:
int flag = 1;//定义一个标记 public void print01(){ synchronized (this){//this称为同步锁对象 if(flag != 1){ try { this.wait();//调用wait方法,使线程处于等待状态。 } catch (InterruptedException e) { e.printStackTrace(); } } Log.d("kwwl","郭"); Log.d("kwwl","靖"); flag =2; this.notify();//调用notify方法,唤醒线程 } } public void print02(){ synchronized (this){ if(flag == 1){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } Log.d("kwwl","黄"); Log.d("kwwl","蓉"); flag =1; this.notify(); } }
同时开启两个线程,分别调用print01和print02方法,代码如下:
new Thread(new Runnable() { public void run() { while (true) { print01(); } } }).start(); new Thread(new Runnable() { public void run() { while (true) { print02(); } } }).start();
在上面print01和print02方法中都使用了synchronized 关键字构成了同步代码块,所以“郭”和“靖”一定同时打印,“黄”和“蓉”一定同时打印。但如果不使用wait方法和notify方法,则会出现“郭靖”打印了很多次才会打印“黄蓉”。而此时使用了wait方法和notify方法,实现了线程间通信功能,则“郭靖”和“黄蓉”轮流交替打印。
说明:this称为同步锁对象,他可以是任意类型的对象,但必须保证两个同步代码块的锁对象是同一个对象。
分析:
假设线程二先执行了,此时判断flag等于1,然后这个线程就会等待,此时线程1就会执行,但线程一执行后flag等于2,并调用notify来唤醒线程,这个方法是随机唤醒使用this锁等待的线程,此时只有线程二处于等待,所以线程二被唤醒。然后若还是线程一执行,那么因为此时flag等于2,所以线程一将被等待,所以就会执行线程二,等等依次执行。
注:如果是三个线程间的通信,可以使用this.notityAll方法,这个方法表示唤醒所有等待的线程。
三,使用ReentrantLock 类实现线程间通信
重要点如下:*首先创建ReentrantLock 对象,然后再得到Condition 对象。
* 如果希望线程等待, 就调用await()方法。
* 如果希望唤醒等待的线程, 就调用signal()方法。
* 这两个方法必须在同步代码中执行, 并且使用同一个ReentrantLock 对象。
代码示例如下:
首先声明两个成员方法:
int flag = 1; private ReentrantLock lock = new ReentrantLock(); Condition c1 = lock.newCondition(); Condition c2 = lock.newCondition(); public void print01(){ lock.lock(); if(flag != 1){ try { c1.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Log.d("kwwl","郭"); Log.d("kwwl","靖"); c2.signal(); lock.unlock(); } public void print02(){ lock.lock(); if(flag != 1){ try { c2.await(); } catch (InterruptedException e) { e.printStackTrace(); } } Log.d("kwwl","黄"); Log.d("kwwl","蓉"); c1.signal();//唤醒c1 lock.unlock(); }
再同时开启两个线程,分别调用两个方法,代码同上。
分析:首先使用ReentrantLock 对象的lock和unlock方法实现了同步代码块。然后又使用Condition类的await方法和signal方法实现了等待唤醒机制,实现了线程间通信。
相关文章推荐
- Java 多线程编程之六:线程之间的通信(附源代码)
- 多线程之间的通信
- 应用java多线程实现server端与多client之间的通信
- 关于Linux下多线程之间通信
- 多进程和多线程之间的通信方式及通信实现步骤小结
- 【多线程】三种方案实现多线程之间相互协作的通信
- java多线程之间的相互通信
- 探究iOS开发中多线程之间的通信
- 自定义NSOperation进行多线程之间的通信(通知、代理、block)
- 多进程及多线程之间同步与通信
- 关于Linux下多线程之间通信
- Java/Android多线程并发、同步,线程之间通信,主、子线程的一些问题(CountDownLatch、CyclicBarrier和Semaphore)
- vc 基于对话框多线程编程实例——线程之间的通信
- 多线程之间的通信
- 关于Linux下多线程之间通信
- 关于Linux下多线程之间通信
- 应用java多线程实现服务器端与多客户端之间的通信
- JAVA基础学习(十二)--多线程一线程之间的通信
- Android 多线程之间的通信交互(Ui线程与子线程之间的通信)Handler,Handler.post(Runnable runnable),runUiThread方式
- java多线程---线程之间的通信