亲宝软件园·资讯

展开

Java Thread多线程开发中Object类详细讲解

健鑫. 人气:0

方法概览

Thread

wait  notify notifyAll方法详解

作用

阻塞阶段

使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒

唤醒阶段

notify会唤醒单个处于阻塞状态的线程,唤醒的线程是随机的

notify和wait都需要写在synchronized代码块里,不然会抛出异常

notifyAll会唤醒所有等待的线程

遇到中断

执行wait方法之后,被中断,会抛出InterruptedException这个异常

代码展示

public class Wait {
    public static void main(String[] args) throws InterruptedException {
        Thread1 thread1 = new Thread1();
        Thread2 thread2 = new Thread2();
        thread1.start();
        Thread.sleep(200);
        thread2.start();
    }
    public static Object object = new Object();
    static class Thread1 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println("Thread1执行");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread1获取锁");
            }
        }
    }
    static class Thread2 extends Thread {
        @Override
        public void run() {
            synchronized (object) {
                object.notify();
                System.out.println("Thread2调用notify");
            }
        }
    }
}
/*
Thread1执行
Thread2调用notify
Thread1获取锁
* */
public class notifyOrAll implements Runnable{
    private static final Object a = new Object();
    public static void main(String[] args) throws InterruptedException {
        Runnable r = new notifyOrAll();
        Thread threada = new Thread(r);
        Thread threadb = new Thread(r);
        Thread threadc = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
//                    a.notifyAll();
                    a.notify();
                    System.out.println(Thread.currentThread().getName() + "notify");
                }
            }
        });
        threada.start();
        Thread.sleep(200);
        threadb.start();
        Thread.sleep(200);
        threadc.start();
    }
    @Override
    public void run() {
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "得到锁");
            try {
                System.out.println(Thread.currentThread().getName() + "wait");
                a.wait();
                System.out.println(Thread.currentThread().getName() + "wait结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
/*
Thread-0得到锁
Thread-0wait
Thread-1得到锁
Thread-1wait
Thread-2notifyAll
Thread-1wait结束
Thread-0wait结束
* */
/*
Thread-0得到锁
Thread-0wait
Thread-1得到锁
Thread-1wait
Thread-2notify
Thread-0wait结束
* */
public class OwnMonitor {
    private static volatile Object a = new Object();
    private static volatile Object b = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("threadA得到a");
                    synchronized (b) {
                        System.out.println("threadA得到锁b");

                        try {
                            System.out.println("threadA释放a");
                            a.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a) {
                    System.out.println("threadB得到a");
                    System.out.println("threadB要获取b");
                    synchronized (b) {
                        System.out.println("threadB得到b");
                    }
                }
            }
        });
        threadA.start();
        Thread.sleep(1000);
        threadB.start();
    }
}
/*
threadA得到a
threadA得到锁b
threadA释放a
threadB得到a
threadB要获取b
* */

特点

当线程从wait状态刚被唤醒时,通常不能直接得到锁,那就会从waiting状态转换到blocked状态,抢到锁之后状态转变为runnable

如果发生异常,则直接跳到Terminated状态

通过wait notify方法实现生产者和消费者

public class ProducerConsumer {
    public static void main(String[] args) {
        Storge storge = new Storge();
        Producer producer = new Producer(storge);
        Consumer consumer = new Consumer(storge);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}
class Producer implements Runnable {
    private Storge storge;
    public Producer(Storge storge) {
        this.storge = storge;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storge.put();
        }
    }
}
class Consumer implements Runnable {
    private Storge storge;
    public Consumer(Storge storge) {
        this.storge = storge;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            storge.take();
        }
    }
}
class Storge {
    private int maxSize;
    private LinkedList<Date> storge;
    public Storge() {
        maxSize = 10;
        storge = new LinkedList<>();
    }
    public synchronized void put() {
        while (storge.size() == maxSize) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        storge.add(new Date());
        System.out.println("已经有了" + storge.size());
        notify();
    }
    public synchronized void take() {
        while (storge.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("拿到了" + storge.poll() + "还剩" + storge.size());
        notify();
    }
}

sleep方法详解

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

特点:和wait不一样,sleep不释放锁

sleep不会释放锁

证明sleep不会释放 synchronized锁

public class SleepSyn implements Runnable{
    public static void main(String[] args) {
        SleepSyn sleepSyn = new SleepSyn();
        new Thread(sleepSyn).start();
        new Thread(sleepSyn).start();
    }
    @Override
    public void run() {
        syn();
    }
    private synchronized void syn() {
        System.out.println(Thread.currentThread().getName() + "获取锁");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "释放锁");
    }
}
/*
* Thread-0获取锁
Thread-0释放锁
Thread-1获取锁
Thread-1释放锁
* */

证明sleep不释放Lock锁

public class sleepLock implements Runnable{
    private static final Lock LOCK = new ReentrantLock();
    @Override
    public void run() {
        LOCK.lock();
        System.out.println(Thread.currentThread().getName() + "获取锁");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            LOCK.unlock();
        }
        System.out.println(Thread.currentThread().getName() + "释放锁");
    }
    public static void main(String[] args) {
        sleepLock sleepLock = new sleepLock();
        new Thread(sleepLock).start();
        new Thread(sleepLock).start();
    }
}
/*
* Thread-0获取锁
Thread-0释放锁
Thread-1获取锁
Thread-1释放锁
* */

sleep响应中断

public class sleepInterrupted implements Runnable{
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new sleepInterrupted());
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(new Date());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("中断");
                e.printStackTrace();
            }
        }
    }
}
/*
* Fri Jan 27 21:11:57 CST 2023
Fri Jan 27 21:11:58 CST 2023
中断
Fri Jan 27 21:11:59 CST 2023
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at java.lang.Thread.sleep(Thread.java:340)
   at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
   at com.jx.JavaTest.ThreadObjectMethod.sleepInterrupted.run(sleepInterrupted.java:21)
   at java.lang.Thread.run(Thread.java:748)
Fri Jan 27 21:12:00 CST 2023
Fri Jan 27 21:12:01 CST 2023
Fri Jan 27 21:12:02 CST 2023
Fri Jan 27 21:12:03 CST 2023
Fri Jan 27 21:12:04 CST 2023
Fri Jan 27 21:12:05 CST 2023
Fri Jan 27 21:12:06 CST 2023
Process finished with exit code 0
* */

总结

sleep方法可以让线程进入waiting状态,不占用CPU资源,但是不释放锁,规定时间之后再运行

休眠期间如果被打断,会抛出异常并清除中断状态

join方法详解

新线程加入,主线程等子线程执行完毕

代码展示

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("所有线程执行完毕");
    }
}
/*
* 开始等待子线程运行
Thread-0执行完毕
Thread-1执行完毕
所有线程执行完毕
* */
/*
* 开始等待子线程运行
所有线程执行完毕
Thread-1执行完毕
Thread-0执行完毕
* */
public class joinInterrupt {
    public static void main(String[] args) {
        Thread main1 = Thread.currentThread();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    main1.interrupt();
                    Thread.sleep(2000);
                    System.out.println("启动");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        System.out.println("join");
        try {
            thread1.join();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "中断");
            // thread1.interrupt();
            e.printStackTrace();
        }
        System.out.println("子线程运行完毕");
    }
}
/*
* join
启动
子线程运行完毕
* */
/*
* join
main中断
子线程运行完毕
java.lang.InterruptedException
   at java.lang.Object.wait(Native Method)
   at java.lang.Thread.join(Thread.java:1252)
   at java.lang.Thread.join(Thread.java:1326)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
启动
Process finished with exit code 0
* */
/*
* join
main中断
子线程运行完毕
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt$1.run(joinInterrupt.java:13)
   at java.lang.Thread.run(Thread.java:748)
java.lang.InterruptedException
   at java.lang.Object.wait(Native Method)
   at java.lang.Thread.join(Thread.java:1252)
   at java.lang.Thread.join(Thread.java:1326)
   at com.jx.JavaTest.ThreadObjectMethod.joinInterrupt.main(joinInterrupt.java:23)
Process finished with exit code 0
* */

join期间,线程处于WAITING状态

public class joinStates {
    public static void main(String[] args) throws InterruptedException {
        Thread main1 = Thread.currentThread();
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println(main1.getState());
                    System.out.println("子线程运行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        System.out.println("join");
        thread.join();
        System.out.println("运行完毕");
    }
}
/*
* join
WAITING
子线程运行结束
运行完毕
* */

yield方法

用来释放CPU时间片,但是不一定能达到预期的效果,因为有时CPU资源不紧张,无需yield

和sleep的区别是:sleep期间不会被再次调度但是yield会立刻处于竞争状态,还会随时再次被调度

加载全部内容

相关教程
猜你喜欢
用户评论