Java多线程——线程间协作方式总结及使用示例
来源:互联网 发布:windows 执行snmpwalk 编辑:程序博客网 时间:2024/05/23 01:29
线程之间的协作方式
方式一、wait()、notify()、notifyAll()
wait()提供了一种在任务之间对活动同步的方式。wait()使你可以等待某个条件发生变化,通常,这种条件将由另一个任务来改变。
wait()会在等待外部世界发生变化的时候将任务挂起(而不是执行空循环,进行忙等待),并且只有在notify()或notifyAll()发生时,这个任务才会被唤醒并去检查所产生的变化。
调用sleep()的时候锁没有被释放,调用yield()也属于这种情况。但是,当一个任务在方法里遇到wait()的调用的时候,线程将被挂起,对象上的锁被释放。
因此,当我们调用wait()的时候就是在声明:”我已经刚刚做完能做的所有事情,因此我要在这里等待,但是我希望其他的synchronized操作在条件合适的情况下能够执行。“
wait()、notify()、notifyAll()有一个比较特殊的方面,那就是这些方法是基类Object的一部分,而不是属于Thread的一部分。此外,这三个方法都必须在同步方法(synchronized修饰的方法)里面调用,否则会报IllegalMonitorStateException。
public class NotifyTest2 implements Runnable { private final Runnable r; public NotifyTest2(Runnable r) { this.r=r; } public void run() { try { TimeUnit.SECONDS.sleep(3); synchronized (r){ //重点:注意这儿的用法! r.notify(); } //r.notify(); 不能在非Synchronized方法里面调用notify()、notifyAll()、wait() } catch (InterruptedException e) { e.printStackTrace(); } }}
要唤醒哪个线程,就必须传入哪个线程的引用,然后该引用调用自身的notify()方法。因为notify()等方法是Object本身的方法,所以只能由自身来调用。这一点不清楚,上面的重点处就可能会出错。
方式二、使用显式的Lock和Condition对象
互斥并允许任务挂起的基本类是Condition,我们可以通过在Condition上调用await()来挂起一个任务,通过signal()、signalAll()来唤醒在这个Condition上挂起的一个或所有任务。
...... private Lock lock=new ReentrantLock(); private Condition condition=lock.newCondition; //...... lock.lock(); //... condition.await(); //... lock.unlock(); //...... lock.lock(); //... condition.signal(): //... lock.unlock(); //...... lock.lock(); //... condition.signalAll(); //... lock.unlock();
方式三、阻塞队列:BlockingQueue
wait()和notifyAll()方法以一种非常低级的方式解决了任务互操作问题,即每次交互时都握手。同步队列则具有更高的抽象级别。同步队列在任何时刻都只允许一个任务插入或移除元素。
如果消费者任务试图从队列中获取元素,而该队列此时为空,那么这个队列会挂起消费者任务,当有新元素进入队列时恢复消费者任务。阻塞队列方式与wait()和notifyAll()相比,要简单和可靠得多。
BlockingQueue<LiftOff> rockets=new LinkedBlockingQueue<LiftOff>(); rockets.put(new LiftOff()); //LiftOff()是一个Runnable LiftOff rocket=rockets.take(); rocket.run();
方式四、使用管道进行输入输出
通过输入/输出在线程间进行通信很有用。线程间可以通过管道进行输入输出,在Java的I/O类库中对应的就是PipedWrite类和PipedReader类。
//在线程1中 PipedWriter out=new PipedWriter(); for(char c='A';c<='z';c++) out.write(c); //在线程2中 PipedReader in=new PipedReader(out);//要传入PipedWriter来构建PipedReader while(true){ System.out.println("Read:"+(char)in.read()+","); }
注意,PipedReader与普通的I/O不同——PipedReader是可中断的。
- Java多线程——线程间协作方式总结及使用示例
- Java 多线程之线程间协作
- 多线程:线程间协作
- java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
- Java多线程之线程协作
- Win32多线程编程(6) — 多线程协作及线程的池化管理
- Win32多线程编程(6) — 多线程协作及线程的池化管理
- Win32多线程编程(6) — 多线程协作及线程的池化管理
- Java多线程之线程间协作 notify与wait的使用
- Java多线程(3):使用Condition中的await、signal进行线程间协作
- java学习之浅谈多线程3--线程间协作
- Java并发编程:线程间协作的两种方式
- java多线程简介及线程创建方式
- Java多线程实践之—协作
- 10 Java并发编程3-线程间协作总结
- java中的多线程——线程创建方式、线程互斥和线程间通信
- java 多线程及线程池总结
- Java多线程总结(1) — 创建线程的两种方式
- 交叉熵是否非负?
- Android高效加载大图、多图解决方案,有效避免程序OOM 摘记
- [HDU] 5544 Ba Gua Zhen
- 网络学习——Unity3D的Time类(UnityEngine.Time)详解
- jsp九大内置对象,作用及方法
- Java多线程——线程间协作方式总结及使用示例
- 文章标题
- C++ 内联函数
- 关于数字编码的小知识
- nginx 常见配置总结
- 前10道题小结
- 51Nod 1107 斜率小于0的连线数量
- C语言:验证哥德巴赫猜想(Goldbach conjecture verification )
- 【一起来学C语言】C语言的组成:表达式