Java中run(), start(), join(), wait(), yield(), sleep()的使用
Run
每个Thread中需要实现的方法, 如果直接调用的话, 会是和单线程一样的效果, 要另起线程需要使用start().
start
新起线程调用run(). 主线程不等待直接往下执行
Yield
Yield会告诉jvm, 它愿意让出当前的处理器使用, 让其他线程被执行. 这意味着它并非在执行非常紧急的任务, 这只是一个hit, 可能会被忽略, 可能并不会发生任何作用. 需要有详细的profiling和benchmarking来保证这个调用达到预期的效果.
- Yield是一个静态和原生的方法
- Yield告诉当前线程, 给予线程池中同等优先级的其他线程被执行的机会.
- Yield并不保证会立即将当前正在执行的线程状态转变为runnable.
- Yield只会将一个线程的状态从Running变成Runnable, 而不是wait或blocked状态.
Join
- 线程实例的join调用, 可以让这个线程执行的开始被关联到另一个线程执行的结束上, 这样直到另一个线程结束后这个线程才会开始执行. 如果对一个线程调用了join, 那么当前running的线程会被block, 直到那个线程执行结束.
- 如果在join中设置了timeout, 那么在timeout后会取消join, 当timeout时, 主线程会变成和任务线程一样的执行候选, 但是这个时间准确度取决于操作系统, 并不能保证是精确的.
- join和sleep一样, 会相应interrupt并抛出一个InterruptedException
如果有一个Thread a, 在a.start()后面(可以使用thread.isAlive()判断). 使用a.join() 可以使主线程等待a执行完. 如果同时有多个线程a, b, c, 而d需要等abc执行完后才能执行, 可以在d start之前使用a.join, b.join, c.join, 也可以把a, b, c的start放到d的run方法里面, 使用a.join, b.join, c.join, 可以用参数设置timeout时间.
- class JoiningThread extends Thread {
- // NOTE: UNTESTED!
- private String name;
- private Thread nextThread;
- public JoiningThread(String name) {
- this(name, null);
- }
- public JoiningThread(String name, Thread other) {
- this.name = name;
- this.nextThread = other;
- }
- public String getName() {
- return name;
- }
- @Override
- public void run() {
- System.out.println("Hello I'm thread ".concat(getName()));
- if (nextThread != null) {
- while(nextThread.isAlive()) {
- try {
- nextThread.join();
- } catch (InterruptedException e) {
- // ignore this
- }
- }
- }
- System.out.println("I'm finished ".concat(getName()));
- }
- }
使用的时候
- public static void main(String[] args) {
- Thread d = WaitingThread("d");
- Thread c = WaitingThread("c", d);
- Thread b = WaitingThread("b", c);
- Thread a = WaitingThread("a", b);
- a.start();
- b.start();
- c.start();
- d.start();
- try {
- a.join();
- } catch (InterruptedException e) {}
- }
sleep(): 需要时间作为参数, 可以被interrupt.
wait(): wait会释放当前持有的锁, 并进入sleep状态. 和join()的区别是, wait需要额外的notify来终止.
notify(): synchronized锁定的是什么资源, 就在什么资源上调用notify. notify会唤醒在当前锁定对象上使用了wait()的一个线程. 要注意的是, 调用notify时并未释放锁定的对象资源, 它只是告诉等待的线程, 你可以醒过来了. 而锁的释放要等到synchronized代码块执行的结束. 所以如果对一个资源调用了notify(), 而调用者本身还需要10秒中才能完成synchronized的代码块, 被唤醒的线程还需要再等10秒才能继续执行.
notifyAll(): 会唤醒当前锁定对象上等待的所有线程, 最高优先级的线程会拿到对象锁并继续执行(这不是完全保证的). 其他和notify是一样的.
上面的类可以改写为
- class WaitingThread extends Thread {
- // NOTE: UNTESTED!
- private Thread previousThread;
- private String name;
- public WaitingThread(String name) {
- this(name, null);
- }
- public WaitingThread(String name, Thread other) {
- this.name = name;
- this.previousThread = other;
- }
- public String getName() {
- return name;
- }
- @Override
- public void run() {
- System.out.println("Hello I'm thread ".concat(getName()));
- // Do other things if required
- // Wait to be woken up
- while(true) {
- synchronized(this) {
- try {
- wait();
- break;
- } catch (InterruptedException e) {
- // ignore this
- }
- }
- }
- System.out.println("I'm finished ".concat(getName()));
- // Wake up the previous thread
- if (previousThread != null) {
- synchronized(previousThread) {
- previousThread.notify();
- }
- }
- }
- }
对于 synchronized, wait 和 notifyAll 的测试. 其中Producer模拟一个队列生产者, Consumer1和Consumer2模拟队列消费者, 队列是同步对象, 得到锁的线程, 会通过wait()或notifyAll()通知其他线程继续尝试得到锁.
Producer.java
- class Producer implements Runnable {
- private final List<Integer> taskQueue;
- private final int MAX_CAPACITY;
- public Producer(List<Integer> sharedQueue, int size) {
- this.taskQueue = sharedQueue;
- this.MAX_CAPACITY = size;
- }
- @Override
- public void run() {
- int counter = 0;
- while (true) {
- try {
- produce(counter++);
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- }
- }
- private void produce(int i) throws InterruptedException {
- System.out.println(Thread.currentThread().getName() + ": produce()");
- synchronized (taskQueue) {
- System.out.println(Thread.currentThread().getName() + ": produce().synchronized >>");
- while (taskQueue.size() == MAX_CAPACITY) {
- System.out.println(Thread.currentThread().getName() + ": produce().synchronized ||");
- taskQueue.wait();
- }
- Thread.sleep(500 + (long)(Math.random() * 500));
- taskQueue.add(i);
- System.out.println(Thread.currentThread().getName() + ": Produced: " + i);
- taskQueue.notifyAll();
- System.out.println(Thread.currentThread().getName() + ": produce().synchronized <<");
- }
- }
- }
Consumer.java
- class Consumer implements Runnable {
- private final List<Integer> taskQueue;
- public Consumer(List<Integer> sharedQueue) {
- this.taskQueue = sharedQueue;
- }
- @Override
- public void run() {
- while (true) {
- try {
- consume();
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- }
- }
- private void consume() throws InterruptedException {
- System.out.println(Thread.currentThread().getName() + ": consume()");
- synchronized (taskQueue) {
- System.out.println(Thread.currentThread().getName() + ": consume().synchronized >>");
- while (taskQueue.isEmpty()) {
- System.out.println(Thread.currentThread().getName() + ": consume().synchronized ||");
- taskQueue.wait();
- }
- Thread.sleep(500 + (long)(Math.random() * 500));
- int i = (Integer) taskQueue.remove(0);
- System.out.println(Thread.currentThread().getName() + ": Consumed: " + i);
- taskQueue.notifyAll();
- System.out.println(Thread.currentThread().getName() + ": consume().synchronized <<");
- }
- }
- }
ProducerConsumerExample.java
- public class ProducerConsumerExample {
- public static void main(String[] args) {
- List<Integer> taskQueue = new ArrayList<Integer>();
- int MAX_CAPACITY = 5;
- Thread tProducer = new Thread(new Producer(taskQueue, MAX_CAPACITY), "Producer");
- Thread tConsumer = new Thread(new Consumer(taskQueue), "Consumer1");
- Thread tConsumer2 = new Thread(new Consumer(taskQueue), "Consumer2");
- tProducer.start();
- tConsumer.start();
- tConsumer2.start();
- }
- }
Java中run(), start(), join(), wait(), yield(), sleep()的使用的更多相关文章
- Java多线程中run(), start(), join(), wait(), yield(), sleep()的使用
Run 每个Thread中需要实现的方法, 如果直接调用的话, 会是和单线程一样的效果, 要另起线程需要使用start(). start 新起线程调用run(). 主线程不等待直接往下执行 Yield ...
- java中sleep和join和yield和wait和notify的区别
1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据.注意该方 ...
- java 中的fork join框架
文章目录 ForkJoinPool ForkJoinWorkerThread ForkJoinTask 在ForkJoinPool中提交Task java 中的fork join框架 fork joi ...
- java中interrupt、join、sleep、notify、notifyAll、wait详解
首先介绍一下中断概念:举个例子容易理解一点 例子:假如你正在给朋友写信,电话铃响了.这时,你放下手中的笔,去接电话.通话完毕,再继续写信.这个例子就表现了中断及其处理过程:电话铃声使你暂时中止当前的工 ...
- 关于多线程中sleep、join、yield的区别
好了.说了多线程,那就不得不说说多线程的sleep().join()和yield()三个方法的区别啦 1.sleep()方法 /** * Causes the currently executing ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
- java中start()、yield、setDeamon()
本节主要说明以下三个问题 start()的启动顺序不代表线程的启动顺序 yeild的作用 守护线程 1.start()与线程启动顺序 package foreverly.cn.chapter1; pu ...
- Java进程与多线程+线程中的join、yield、wait等方法+synchronized同步锁使用
首先了解什么是多线程与进程 进程:是一个执行过程,动态的概念 --->会分配内存线程:是进程的一个单元,线程是系统最小的执行单元 详解: http://blog.csdn.net/luoweif ...
- 可惜Java中没有yield return
项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...
随机推荐
- run() 和 start() 的区别
1) start: 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面(指主线程下面)的代码.通过调用Thread类的start()方法来启动一个 ...
- iOS文件解压&&数据加密
一文件压缩.这里我们需要一个第三方SSZipArchive(需要添加libz.td) #import "ViewController.h" #import "SSZipA ...
- 一个统计报表sql问题
今天朋友问我了一个统计报表的sql问题.我弄了好久.终于算是写出来了.这里记录下. 问题: id--------------name--------------addtime1 ...
- Harrypotter
#include<iostream> using namespace std; int main() { ]={}; int a,b,c,d; cout<<"请输入总 ...
- 抛弃NVelocity,来玩玩Razor
对于内容型,不易变动的东西我们都希望给它来个静态化,还有种情况就是比如新浪云不支持.net,为了能跑起我们的网站, 只能放些静态页面上面,外加jsonp来实现交互,我们知道.net中有很多模板引擎,但 ...
- 0021 Java学习笔记-面向对象-包、构造器
封装 面向对象的三大特征: 封装 继承 多态 封装: 将对象的状态信息隐藏,不允许外部程序直接访问 通过该类提供的方法来访问和操作 有啥用: 隐藏类的实现细节 在方法中加入控制逻辑,限制对成员变量的不 ...
- Python基础之生成器
1.生成器简介 首先请确信,生成器就是一种迭代器.生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中.另外,对于生成器的特殊语法支持使得编写一个生成器比 ...
- asp.net服务器控件onclick带参数
服务器控件处理参数随笔 正确: <asp:CheckBox ID="cbComplareProduct" runat="server" Text=&quo ...
- gvim的菜单乱码解决方法
gvim的菜单乱码解决方法: (乱码是由于系统内码不兼容导致,系统内码包括gb2312 gb18030 utf-8 utf-16[unicode]等) 生成文件 ~/.gvimrc 并添加如下语句:s ...
- devtmpfs文件系统创建设备节点
分类: LINUX 原文地址:devtmpfs文件系统创建设备节点 作者:wangbaolin719 http://blog.chinaunix.net/uid-27097876-id-4334356 ...