博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程中run(), start(), join(), wait(), yield(), sleep()的使用
阅读量:6259 次
发布时间:2019-06-22

本文共 6624 字,大约阅读时间需要 22 分钟。

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
taskQueue; private final int MAX_CAPACITY; public Producer(List
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
taskQueue; public Consumer(List
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
taskQueue = new ArrayList
(); 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(); }}

 

 

 

 

转载地址:http://fcqsa.baihongyu.com/

你可能感兴趣的文章
英语发音纠正
查看>>
.Net三层架构
查看>>
九度 题目1335:闯迷宫 题目1365:贝多芬第九交响曲
查看>>
Struts2异常处理配置
查看>>
pace.js和NProgress.js两个加载进度插件的一点小总结
查看>>
Oracle数据库该如何着手优化一个SQL
查看>>
sql语句中charindex的用法 可用于截取字符串
查看>>
Mina 中遇到SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder"
查看>>
SDRAM 学习笔记(一)
查看>>
Android开发日记(七)
查看>>
Python多线程
查看>>
c++ 动态分配二维数组 new 二维数组
查看>>
在source insight中集成astyle
查看>>
一个canonical标签解决site不在首页的问题
查看>>
[Hibernate开发之路](2)Hibernate问题
查看>>
HDU - 4118 Holiday&#39;s Accommodation
查看>>
函数式编程——C#理解
查看>>
java数组或集合返回空的问题
查看>>
【转】gc日志分析工具
查看>>
java多线程系列2-线程控制
查看>>