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区别:是否随时可能再次被唤醒

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值