Thread和Object中重要的方法


一、Object类中的wait、notify、notifyAll 

1、作用、用法

  • wait、notify基本使用
/**
 * 展示wait和notify的基本用法
 *
 * @author wjh
 * @date 2020-03-05 10:45
 */
public class Wait {
    public static Object object = new Object();

    static class Thread1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("线程" + Thread.currentThread().getName() + "开始运行了");
                try {
                    // 释放锁
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁");
            }
        }
    }

    static class Thread2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                // 线程2唤醒
                object.notify();
                System.out.println("线程" + Thread.currentThread().getName() + "调用了notify");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(100);
        thread2.start();
    }
}

运行结果: 

  • notify、notifyAll使用

/**
 * 3个线程,线程1,线程2首先被阻塞,线程3唤醒它们。分别使用notify和notifyAll
 *
 * @author wjh
 * @date 2020-03-05 11:05
 */
public class WaitNotifyAll implements Runnable {
    private static 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.wait();
                System.out.println("线程" + Thread.currentThread().getName() + "工作结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        WaitNotifyAll waitNotifyAll = new WaitNotifyAll();
        Thread threadA = new Thread(waitNotifyAll);
        Thread threadB = new Thread(waitNotifyAll);
        Thread threadC = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    resourceA.notifyAll();
                    System.out.println("线程" + Thread.currentThread().getName() + "调用了notifyAll方法");
                }
            }
        });
        threadA.start();
        threadB.start();
        Thread.sleep(200);
        threadC.start();
    }
}

运行结果:

如果是使用notify,只能唤醒一个线程,剩下的没人唤醒程序无法结束运行

  • wait只释放当前的锁证明

/**
 * 证明wait只释放当前的那把锁
 *
 * @author wjh
 * @date 2020-03-05 11:18
 */
public class WaitNotifyReleaseOwnMonitor {
    private static volatile Object resourceA = new Object();
    private static volatile Object resourceB = new Object();

    public static void main(String[] args) {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (resourceA) {
                    System.out.println("线程" + Thread.currentThread().getName() + "获取到resourceA");
                    synchronized (resourceB) {
                        System.out.println("线程" + Thread.currentThread().getName() + "获取到resourceB");
                        try {
                            // 释放resourceA
                            resourceA.wait();
                            System.out.println("线程" + Thread.currentThread().getName() + "释放resourceA");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (resourceA) {
                    System.out.println("线程" + Thread.currentThread().getName() + "获取到resourceA");
                    System.out.println("线程" + Thread.currentThread().getName() + "尝试获取resourceB");
                    synchronized (resourceB) {
                        System.out.println("线程" + Thread.currentThread().getName() + "获取到resourceB");
                    }
                }
            }
        });
        threadA.start();
        threadB.start();
    }
}

运行结果:

线程A首先获取到了A锁和B锁,然后释放了A锁但是还持有B锁,然后线程B获取到A锁,等待获取B锁,而A没有唤醒不能释放B锁,程序陷入死锁


2、特点、性质

  • 必须先拥有monitor(Java中synchronized)
  • notify只能唤醒其中一个线程
  • 都属于Object类,所以每一个类有拥有这些方法
  • 类似功能的Condition
  • 同时拥有多个锁,wait只会释放当前对象这把锁

二、Thread类中重要的方法

1、sleep

作用:能让线程在预期的时间执行,其他时候不占用CPU资源

特点:sleep不会释放锁(包括synchronized 和 lock)、sleep方法响应中断

演示:

  • 1、不释放synchronized锁

/**
 * 演示线程sleep不释放synchronized的monitor,等sleep时间结束后,正常结束任务才会释放锁
 *
 * @author wjh
 * @date 2020-03-05 13:03
 */
public class SleepDontReleaseMonitor implements Runnable {
    public static void main(String[] args) {
        SleepDontReleaseMonitor sleepDontReleaseMonitor = new SleepDontReleaseMonitor();
        Thread threadA = new Thread(sleepDontReleaseMonitor, "A");
        Thread threadB = new Thread(sleepDontReleaseMonitor, "B");
        threadA.start();
        threadB.start();
    }

    @Override
    public void run() {
        syn();
    }

    private synchronized void syn() {
        System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程" + Thread.currentThread().getName() + "退出同步代码块");
    }
}

结果:

  • 2、不释放lock
/**
 * 演示线程sleep不释放synchronized的monitor,等sleep时间结束后,正常结束任务才会释放锁
 *
 * @author wjh
 * @date 2020-03-05 13:03
 */
public class SleepDontReleaseLock implements Runnable {
    public static void main(String[] args) {
        SleepDontReleaseLock sleepDontReleaseLock = new SleepDontReleaseLock();
        Thread threadA = new Thread(sleepDontReleaseLock, "A");
        Thread threadB = new Thread(sleepDontReleaseLock, "B");
        threadA.start();
        threadB.start();
    }

    private static final Lock lock = new ReentrantLock();

    @Override
    public void run() {
        lock.lock();
        System.out.println("线程" + Thread.currentThread().getName() + "获取到了锁");
        try {
            Thread.sleep(1000);
            System.out.println("线程" + Thread.currentThread().getName() + "sleep结束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

结果:

  • 3、响应中断
/**
 * @author wjh
 * @date 2020-03-05 13:17
 */
public class SleepInterrupted implements Runnable {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println(new Date());

                TimeUnit.SECONDS.sleep(1);
            }
        } catch (InterruptedException e) {
            System.out.println("线程被中断了");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new SleepInterrupted());
        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.interrupt();
    }
}

结果:


sleep与wait/notify的异同: 

  • 相同

1、阻塞

2、响应中断

  • 不同

1、wait/notify需要在同步代码块中,sleep不需要

2、wait能释放锁,sleep不能

3、所属类不同,wait/notify属于Object类,sleep属于Thread类

4、时间的指定,如果wait不指定时间就需要别人唤醒


2、join

作用:使线程等待调用线程执行完毕

演示:

  • 1、基本用法
/**
 * @author wjh
 * @date 2020-03-05 13:35
 */
public class join {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行完毕");
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行完毕");
            }
        });

        thread1.start();
        thread2.start();
        System.out.println("开始等待子线程运行完毕");
        thread1.join();
        thread2.join();
        System.out.println("所有子线程运行完毕");
    }
}

结果:

  • 2、演示中断
/**
 * @author wjh
 * @date 2020-03-05 13:42
 */
public class JoinInterrupt {
    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mainThread.interrupt();
                    Thread.sleep(5000);
                    System.out.println("线程执行完毕");
                } catch (InterruptedException e) {
                    System.out.println("子线程中断");
                }
            }
        });
        thread.start();
        System.out.println("等待子线程执行完毕");
        try {
            thread.join();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "线程被中断");
            thread.interrupt();
        }
        System.out.println("子线程执行完毕");
    }
}

结果:

  • 3、join的线程状态
/**
 * @author wjh
 * @date 2020-03-05 13:50
 */
public class JoinThreadState {
    public static void main(String[] args) throws InterruptedException {
        Thread mainThread = Thread.currentThread();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println(mainThread.getName() + "线程状态为:" + mainThread.getState());
                    System.out.println("子线程运行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start();
        System.out.println("等待子线程运行完毕");
        thread.join();
        System.out.println("子线程运行完毕");
    }
}

结果:


join的等价代码 :也可以实现join的效果

        synchronized (thread) {
            thread.wait();
        }

3、yield

作用:释放CPU时间片

定位:JVM不保证遵循

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值