我是靠谱客的博主 狂野大雁,最近开发中收集的这篇文章主要介绍Thread和Object类的重要方法Thread和Object类的重要方法详解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Thread和Object类的重要方法详解

方法概览

image-20201209210337860

wait、notify、notifyAll

当一个线程调用了wait方法,则进入阻塞状态(blocked、waiting、timed_waiting),只有下面四种情况会被唤醒

  • 另一个线程调用了这个对象的notify()方法且刚好被唤醒的是本线程
  • 另一个线程调用这个对象的notifyAll()方法
  • 过了wait(long timeout)规定的超时时间,如果传入0就是永久等待
  • 线程自身调用了interrupt方法

notify 和notifyAll需要在synchronized关键字下运行

package com.hasson.ThreadObjectCommonMethods;

public class WaitAll implements Runnable {
    private static final Object resourceA = new Object();

    @Override
    public void run() {
        synchronized (resourceA) {
            System.out.println(Thread.currentThread().getName() + "拿到了resourceA");
            try {
                System.out.println(Thread.currentThread().getName() + "要释放resourceA");
                resourceA.wait();
                System.out.println(Thread.currentThread().getName() + "释放resourceA了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r = new WaitAll();
        Thread threadA = new Thread(r);
        Thread threadB = new Thread(r);
        Thread threadC = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    resourceA.notify();
                    System.out.println(Thread.currentThread().getName() + "使用了notifyAll()");
                }
            }
        });
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
        threadC.start();
    }
}
//Thread-0拿到了resourceA
//Thread-0要释放resourceA
//Thread-1拿到了resourceA
//Thread-1要释放resourceA
//Thread-2使用了notifyAll()
//Thread-0释放resourceA了

使用synchronized、wait、notify实现一个生产者消费者

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public class ProducerConsumerMonitor {
    public static void main(String[] args) {
        EventStorage storage = new EventStorage();
        Thread producer = new Thread(new Producer(storage));
        Thread consumer = new Thread(new Consumer(storage));
        producer.start();
        consumer.start();

    }

}

class EventStorage {
    private int maxSize;
    private List<Date> storage;

    public EventStorage() {
        maxSize = 10;
        storage = new LinkedList<>();
    }

    public synchronized void put() {
        while (storage.size() == maxSize) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        storage.add(new Date());
        System.out.println("仓库里有了" + storage.size() + "个产品");
        notify();
    }

    public synchronized void take() {
        while (storage.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "拿到了" + storage.remove(0) + ",");
        notify();
        System.out.println("仓库里还有" + storage.size() + "个产品");
    }
}

class Consumer implements Runnable {
    private EventStorage storage;

    public Consumer(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.take();
        }
    }
}

class Producer implements Runnable {
    private EventStorage storage;

    public Producer(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storage.put();
        }
    }
}

image-20201211202819326

两个进程交替打印0-100

public class OddEvenSyn {
    private static int count;
    private static Object lock = new Object();

    public static void main(String[] args) {
        Integer index = new Integer(0);
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (count < 50) {
                    synchronized (lock) {
                        System.out.println(Thread.currentThread().getName() + "尝试进来了");
                        if (count % 2 == 0) {
                            System.out.println(Thread.currentThread().getName() + "打印了" + count);
                            count++;
                        }
                    }
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (count < 50) {
                    synchronized (lock) {
                        System.out.println(Thread.currentThread().getName() + "尝试进来了");
                        if (count % 2 == 1) {
                            System.out.println(Thread.currentThread().getName() + "打印了" + count);
                            count++;
                        }
                    }
                }
            }
        });
        thread1.start();
        thread2.start();
    }
}

synchronized的方法比较低效

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xLTXxupn-1610348438210)(pics/7/image-20201211210510444.png)]

某个线程容易多次获得锁,所以应该使用wait和notify

  1. 拿到锁就立即打印
  2. 打印完,唤醒其他线程,就休眠

这里要注意的是 要用lock.wait(),不然就是默认是用自己的。

public class OddEvenWaitNotify {
    private static int count = 0;
    private static Object lock = new Object();

    static class Runner implements Runnable {
        @Override
        public void run() {
            while (count <= 100) {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + "打印了" + count);
                    count++;
                    lock.notify();
                    if (count <= 100)
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
            }
        }
    }


    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runner());
        Thread thread2 = new Thread(new Runner());
        thread1.start();
        thread2.start();
    }
}

sleep

sleep不释放锁(synchronized,lock),和wait不同

TimeUnit.SECONDS.sleep(1);

image-20201212192433325

不同

image-20201212192547422

join

作用

因为新的线程加入了我们,所以我们要等到他执行完再出发

用法

main等待thread1执行完毕,注意谁等谁。join(0)和wait(0)都是指无限时间,直到被唤醒

原理

Thread类实现完之后会使用一个notify的原生代码(c++第层),join实际上就是调用了一个wait(0)方法

image-20201212195405192等价的

  • 在join期间,线程处于waiting状态

yield

作用:

释放我的CPU时间片

定位:

JVM不保证遵循,一般不使用

yield和sleep区别:是否随时可能再次被唤醒

最后

以上就是狂野大雁为你收集整理的Thread和Object类的重要方法Thread和Object类的重要方法详解的全部内容,希望文章能够帮你解决Thread和Object类的重要方法Thread和Object类的重要方法详解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部