【Java并发】Thread和Object类的重要方法


在这里插入图片描述

wait, notify, notifyAll 方法详解

Object类的方法。因此是对象的方法。

阻塞阶段:获取了对象的modify锁,进入休眠
唤醒方法:

  • 另一个线程调用这个对象的notify()方法且刚好唤醒的是本线程;
  • 另一个线程调用这个对象的notifyAll()方法;
  • 过了wait()等待的时间;
  • 等待的过程中调用interrupt()也会被唤醒;

遇到中断:抛出异常,释放锁。

特点性质:用必须先拥有monitor、只能唤醒一个、属于Object类、考虑同时持有多个锁的情况

手写生产者消费者设计模式

需要实现一个public类,三个单独的类,分别实现仓库(构造器:构造仓库,方法:get,take),消费者模式(构造器,继承Runnable重写run,调用take方法),生产者模式(构造器,继承Runnable,调用put方法)

package threadObjectClassCommonMethods;

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

/**
 * @Author: chenzuoZhang
 * @package: threadObjectClassCommonMethods
 * @time: 2020/8/17
 * @TODO: 用wait/notify实现生产者消费者模式
 */
public class ProducerConsumerModel {
    public static void main(String[] args) {
        EventStorage eventStorage = new EventStorage();
        Producer producer = new Producer(eventStorage);
        Consumer consumer = new Consumer(eventStorage);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}
// 实现生产者模式
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();
        }
    }
}
// 实现消费者模式
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();
        }
    }
}

// 建立仓库类,实现get和take方法
class EventStorage{
    private int maxSize;
    private LinkedList<Date> storage;

    public EventStorage(){
        maxSize = 10;
        this.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("拿到了 "+storage.poll()+"物品,现在容量为"+storage.size());
        notify();
    }
}

奇偶线程打印

package threadObjectClassCommonMethods;
/**
 * @Author: chenzuoZhang
 * @TODO: 采用wait和notify提高效率  方法:拿到锁就打印,然后唤醒其他的,自己休眠
 */
public class OddAndEven2 {
    private static final Object lock = new Object();
    private static int count = 0;
    public static void main(String[] args) {
        new Thread(new TurningRunner(),"0").start();
        new Thread(new TurningRunner(),"1").start();
    }
    static class TurningRunner implements Runnable{
        @Override
        public void run() {
            while (count<100){
                synchronized (lock){
                    System.out.println(Thread.currentThread().getName()+count++);
                    // 注意,这里一定是lock.notifyAll(); 而不是notifyAll()
                    lock.notifyAll();
                    if (count<100) {
                        try {
                            // 注意,这里一定是lock.wait(); 而不是wait() 否则会休眠主线程?
                            lock.wait();
                            System.out.println(Thread.currentThread().getName());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

为什么这几个方法在Object方法里,而sleep在Thread里

因为这几个操作是锁的操作,都是绑定于对象的,所有的对象都是可以作为所队形。sleepThread级别的。
Thread类不适合作为锁。

sleep方法详解

sleep让线程进入waiting状态,并且不占用CPU资源。sleep方法在时间未到时候不会释放锁的,但是wait是释放锁的。sleep方法是可以响应中断的,抛出中断并清除中断状态。

wait/notify、sleep的异同

相同:都是可以让线程进入阻塞状态;可以相应中断
不同:wait/notify是Object类;需要在同步方法中进行执行,sleep不需要;释放锁的区别;sleep必须传参。

  • sleep() 和 wait() 有什么区别?
  1. sleep() 是 Thread 类的静态本地方法;wait() 是Object类的成员本地方法
  2. sleep() 方法可以在任何地方使用;wait() 方法则只能在同步方法或同步代码块中使用,否则抛出异常Exception in thread “Thread-0” java.lang.IllegalMonitorStateException
  3. sleep() 会休眠当前线程指定时间,释放 CPU 资源,不释放对象锁,休眠时间到自动苏醒继续执行;wait() 方法放弃持有的对象锁,进入等待队列,当该对象被调用 notify() / notifyAll() 方法后才有机会竞争获取对象锁,进入运行状态
  4. JDK1.8 sleep() wait() 均需要捕获 InterruptedException 异常

join方法

作用:因为新的线程加入了我们,所以我们要等他执行完再出发;
用法:main等待thread执行完毕。
当等待其他线程join期间,主线程处于waiting状态。
本质上还是调用了wait(),最后Thread方法实现notify。

yield方法

作用:释放CPU时间片,线程状态依然是Runnable。不释放锁。

与sleep的区别,sleep方法不是随时可以被调度的,yield可以被随时调度。

获取当前线程引用,Thread.currentThread()方法

Start和run方法

stop,suspend,resume方法

被弃用

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值