Java Thread多线程开发中Object类怎样使用
发布时间:2023-03-21 11:04:14 所属栏目:教程 来源:
导读:方法概览
Thread
Java Thread多线程开发中Object类怎么使用
wait notify notifyAll方法详解
作用
阻塞阶段
使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒
Thread
Java Thread多线程开发中Object类怎么使用
wait notify notifyAll方法详解
作用
阻塞阶段
使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒
|
方法概览 Thread Java Thread多线程开发中Object类怎么使用 wait notify notifyAll方法详解 作用 阻塞阶段 使用了wait方法之后,线程就会进入阻塞阶段,只有发生以下四种情况中的其中一个,线程才会被唤醒 另一个线程调用了这个线程的notify方法,刚好唤醒的是本线程 另一个线程调用了这个对象的notifyAll方法 过了wait规定的超时时间 线程调用了interrupt 唤醒阶段 notify会唤醒单个处于阻塞状态的线程,唤醒的线程是随机的 notify和wait都需要写在synchronized代码块里,不然会抛出异常 notifyAll会唤醒所有等待的线程 遇到中断 执行wait方法之后,被中断,会抛出InterruptedException这个异常 代码展示 展示wait和notify的基本用法 该代码执行wait方法之后会释放锁,然后thread2执行notify方法 notify方法执行完毕之后,并没有立即释放锁,而是接着执行之后的代码,也就是打印“Thread2调用notify”这句话 thread2执行完毕之后,会进行释放锁,thread1才会继续执行 在此期间,thread1虽然被唤醒,但是一直在等待thread2同步代码块里面的代码执行完毕 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获取锁 * */ notify和notifyAll的展示 第一个输出:threadc调用notifyAll 第二个输出:threadc调用notify 调用notify的时候,程序并没有结束,threadb陷入等待 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结束 * */ 只释放当前monitor 证明wait只释放当前的那把锁 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 * */ 特点 执行这些方法必须先获取锁 notify只能换取一个,而且是随机的 都属于Object。任何对象都可以调用 都是native final修饰的 当线程从wait状态刚被唤醒时,通常不能直接得到锁,那就会从waiting状态转换到blocked状态,抢到锁之后状态转变为runnable 如果发生异常,则直接跳到Terminated状态 通过wait notify方法实现生产者和消费者 将storge当作生产者和消费者进行工作的仓库 如果storge中没有数据,生产者就开始wait 如果storge中数据满了,消费者就开始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响应中断 抛出InterruptedException 会清除中断状态 中断之后,抛出异常继续执行 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方法详解 新线程加入,主线程等子线程执行完毕 代码展示 前一个结果是使用join 后一个结果是没使用join 可知使用join之后,主线程会等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执行完毕 * */ 遇到中断 第一个的运行结果是主线程没中断的打印结果 第二个的运行结果是join期间进行中断的打印结果,可知在打印了“子线程运行完毕”之后,依然打印了“启动”两个字,可知会造成运行混乱 可以在捕获异常的代码块中,将join的线程也中断,可以解决上面的问题 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会立刻处于竞争状态,还会随时再次被调度 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
