【多线程】三种方案实现多线程之间相互协作的通信
来源:互联网 发布:知乎周刊 编辑:程序博客网 时间:2024/05/22 04:34
在并发编程中,经常会遇到多个线程之间需要相互协作的情况,即并不是多个线程同时执行,而是按照一定的顺序循环执行的情况。那么怎样去实现这种效果呢?这里介绍三种方案。这里都以子线程循环10次,然后主线程循环10次,然后往复循环50次的思路来做例子。在下面的例子中flag代表一个共享变量。
一、synchronized+notify+wait+flag
public class communication01 { public static void main(String[] args){ final besiness b=new besiness(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++){ b.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { b.main(i); } }} class besiness{ private static boolean flag=true;//flag为true时允许main访问,为false时允许suB访问 public synchronized void main(int i){ while(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("main thread==" + j + ",loop of " + i); } flag=false; this.notify(); } public synchronized void sub(int i){ while (flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 10; j++) { System.out.println("sub thread==" + j + ",loop of " + i); } flag=true; this.notify(); } }
这种方案是通过对两个线程中分别要执行的方法加锁synchronized,保证每次执行main时不被sub打断,执行sub循环时,不被main打断。这里采用了对象object的notify和wait来实现线程之间的通信。当main方法执行完成后,让执行main方法的线程等待,等待sub方法执行完成后,通知(notify)main线程然后继续执行。这种方式有一个缺点,由于notify和wait使用的是Object的方法,所以不能单独的让某个特定的线程收到通知或者让他等待,而在存在多个线程同时等待时,只能通过notifyAll来通知所有的线程。不够灵活。
二、lock+condition+flag
public static void main(String[] args){ final besiness b=new besiness(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++){ b.sub2(i); } } }).start(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++){ b.sub3(i); } } }).start(); for (int i = 1; i <= 50; i++) { b.main(i); } } static class besiness{ private int flag=1;//flag为true时允许main访问,为false时允许suB访问 //condition1来控制main和sub2之间的循环通信 Condition condition1=lock.newCondition() ; //condition2来控制sub2和sub3之间的循环通信 Condition condition2=lock.newCondition() ; //condition1来控制main和sub3之间的循环通信 Condition condition3=lock.newCondition() ; public void main(int i){ lock.lock(); try{ while(flag!=1){ try { condition1.await(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 20; j++) { System.out.println("main thread==" + j + ",loop of " + i); } flag=2; condition2.signal(); }finally { lock.unlock(); } } public void sub2(int i){ lock.lock(); try{ while ( flag !=2){ try { condition2.await(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 20; j++) { System.out.println("sub2 thread==" + j + ",loop of " + i); } flag=3; condition3.signal(); }finally { lock.unlock(); } } public void sub3(int i){ lock.lock(); try{ while ( flag !=3){ try { condition3.await(); } catch (InterruptedException e) { e.printStackTrace(); } } for (int j = 1; j <= 20; j++) { System.out.println("sub3 thread==" + j + ",loop of " + i); } flag=1; condition1.signal(); }finally { lock.unlock(); } } }
这种方式是利用了Java5中提供的lock和condition,利用共享变量flag来实现线程之间的相互通信。同时在这个小例子中,相比上一个例子中增加了一个线程的循环。这是为了体现使用condition的优点。使用condition可以非常灵活的去控制线程与线程之间的通信。因为在一个类中可以创建多个condition的实例,我们可以通过condition不同的实例的signal和await方法来标识不同的两个线程之间相互通信的标识,而不是统一使用object的notify和wait方法了。同时利用lock方法可以利用锁的重入机制实现更加灵活的锁的应用。可以在需要的时候加锁或解锁。这样我们就可以实现多个线程之间的协调通信了。
三、semaphere+flag
public static void main(String[] args){ final besiness b=new besiness(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++){ b.sub(i); } } }).start(); for (int i = 1; i <= 50; i++) { b.main(i); } } static class besiness{ private int flag=1; final Semaphore sp=new Semaphore(1);//声明一个信号,共享一个资源,每次只能允许一个线程执行 public void main(int i){ try { sp.acquire(); while(flag!=1){ sp.release(); } for (int j = 1; j <= 10; j++) { System.out.println("main thread==" + j + ",loop of " + i); } flag=2; } catch (InterruptedException e) { e.printStackTrace(); }finally { sp.release(); } } public void sub(int i){ try{ try { sp.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } while (flag !=2){ sp.release(); } for (int j = 1; j <= 10; j++) { System.out.println("sub thread==" + j + ",loop of " + i); } flag=1; sp.release(); }finally { sp.release(); } } }
这里semaphere代表一个信号量,它可以指示共享资源的个数,也就是同时访问资源的线程个数。这里主要通过semaphere的acquire和release实现锁的功能从而实现线程之间的通信。利用semaphere不仅可以实现多个线程协调循环通信,在必要时还可以控制同一时间访问资源的个数。更加的灵活和方便。以上是实习多个线程之间相互协调通信的几种方案。
1 1
- 【多线程】三种方案实现多线程之间相互协作的通信
- 【多线程】三种方案实现多线程之间相互协作的通信
- java多线程(三)线程之间的通信
- 多线程之间的通信
- 多线程之间的通信
- 多线程之间的通信
- 多线程之间的通信
- 多线程之间的通信
- Condidtion实现多线程之间的线程通信
- VC中利用多线程技术实现线程之间的通信(三)---线程之间的同步
- 多线程-实现多线程的几种方案
- 多线程的实现方案
- CountDownLatch 实现多线程协作
- java多线程之间的通信
- 模拟多线程之间的通信
- 多线程-线程之间的通信
- Java多线程之间的通信
- Windows多线程之间的通信
- 201. Bitwise AND of Numbers Range
- 操蛋的Camera V2
- html jstl嵌套jquery代码
- 使用 CXF 做 webservice 简单例子
- LeetCode 263. Ugly Number
- 【多线程】三种方案实现多线程之间相互协作的通信
- 【HDU 1950】Bridging signals(LIS算法求最长上升子序列)
- Failed to instantiate * using constructor public * with arguments **
- 重复元素的删除问题
- Android基本控件复习笔记(一)
- 【CodeForces】371C - Hamburgers(二分)
- c#之用StreamWriter追加写文件
- Ubuntu上搭建samba服务器并远程挂载
- HeadFirst设计模式读书笔记——简单工厂模式