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()的使用的更多相关文章
- 关于多线程中sleep、join、yield的区别
好了.说了多线程,那就不得不说说多线程的sleep().join()和yield()三个方法的区别啦 1.sleep()方法 /** * Causes the currently executing ...
- Java中run(), start(), join(), wait(), yield(), sleep()的使用
run(), start(), join(), yield(), sleep() 这些是多线程中常用到的方法. run(): 每个Thread中需要实现的方法, 如果直接调用的话, 会是和单线程一样的 ...
- Java 多线程中run() 与 start() 的不同
区别:调用start方法实现多线程,而调用run方法没有实现多线程 Start: 用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码.通过调 ...
- Java多线程中的常用方法
本文将带你讲诉Java多线程中的常用方法 Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...
- java 多线程中的wait方法的详解
java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...
- Java多线程中的竞争条件、锁以及同步的概念
竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作 ...
- 进程?线程?多线程?同步?异步?守护线程?非守护线程(用户线程)?线程的几种状态?多线程中的方法join()?
1.进程?线程?多线程? 进程就是正在运行的程序,他是线程的集合. 线程是正在独立运行的一条执行路径. 多线程是为了提高程序的执行效率.2.同步?异步? 同步: 单线程 异步: 多线程 3.守护线程? ...
- java多线程中的三种特性
java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...
- java多线程中并发集合和同步集合有哪些?区别是什么?
java多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...
随机推荐
- 转 iOS获取软键盘的高度
- (void)viewDidLoad { [super viewDidLoad]; //增加监听,当键盘出现或改变时收出消息 [[NSNotificationCenter defaultCenter ...
- 7. python 字符串格式化方法(2)
7. python 字符串格式化方法(2) 紧接着上一章节,这一章节我们聊聊怎样添加具体格式化 就是指定替换字段的大小.对齐方式和特定的类型编码,结构如下: {fieldname!conversion ...
- python笔记30-docstring注释添加变量
前言 python里面添加字符串注释非常简单,如何将变量放入 python 的函数注释里面呢? docstring也就是给代码加注释的内容了,python可以给函数,类.方法,模块添加注释内容,注释标 ...
- Spring 反射注入+全注解注入
Spring IoC容器会先把所有的Bean都进行实例化,不管是要用到的火鼠用不到的,如果你想暂时不进行Bean的实例化,要用到属性lazy-init="true". Spring ...
- 如何中断正在执行IO的 Quartz 作业
Interrupt a Quartz job that doing IO 如果你想中断正在执行IO的 Quartz 作业,在你使用 InterruptibleChannel 时这是可行的.引用一下Or ...
- iOS抽屉效果
源代码下载 抽屉效果第三方类库下载 所需第三方类库下载 側拉栏抽屉效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTUhUaW9z/font/5a6L ...
- #line 的作用是改变当前行数和文件名称
#line 的作用是改变当前行数和文件名称,它们是在编译程序中预先定义的标识符命令的基本形式如下: #line number["filename"]其中[]内的文件名可以省略. ...
- 通过java读取HDFS的数据 (转)
原文链接:通过java读取HDFS的数据 通过JAVA直接读取HDFS中的时候,一定会用到FSDataInputStream类,通过FSDataInputStream以流的形式从HDFS读数据代码如下 ...
- 3 Sum leetcode java
题目: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find al ...
- Bootstrap学习js插件篇之下拉菜单
案例 通过此插件可以为几乎所有东西添加下拉菜单,包括导航条.标签页.胶囊式按钮. 用于导航条 导航条分为四个部分.第一部分导航头,第二部分导航列,第三部分form查询表单,第四部分导航列. <n ...