高并发设置一
来源:互联网 发布:思科log 端口 编辑:程序博客网 时间:2024/04/28 01:02
等待(wait) 和通知(notify)
这两个方法并不在 Thread 类中,而是输出 Object 类。
public final void wait() throws InterruptedException public final native void notify()
当线程 A 中调用 obj.wait(), A 就会转为等待状态。直到其他线程调用了 obj.notify().这时,obj 就成为多线程间有效通信手段。wait() 和 notify 如何工作?一个线程调用 object.wait() --> 进入 object 对象的等待队列--> object.notify() 被调用 --> 从等待队列中随机选择一个线程唤醒。选择 是不公平的,完全随机的。例子:
public class Thread_1 implements Runnable { public void run() { System.out.println("线程1"); //线程1 进入等待 try { Object.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程_1 执行结束"); } }
抛出异常
Exception in thread "main" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.xc.blackCap.thread.Thread_1.run(Thread_1.java:12) at com.xc.blackCap.thread.ObjectWaitAndNotify.main(ObjectWaitAndNotify.java:11) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
分析: 代码中没有 synchronzied 监视对象修改之后
public class Thread_1 implements Runnable { public void run() { System.out.println("线程1"); //线程1 进入等待 try { Object object = new Object(); synchronized (object) { object.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程_1 执行结束"); } }
声明两个线程测试 wait() 和 notify()
public class Thread_1 extends Thread { final static Object object = new Object(); public void run() { System.out.println("线程1"); //线程1 进入等待 synchronized (object) { try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("线程_1 执行结束"); } } public class Thread_2 extends Thread { final static Object object = new Object(); public void run() { System.out.println("线程_2"); synchronized (object) { //线程_2 唤起 object.notify(); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程_2 执行结束"); } }
执行结果: 线程1 一直被挂起。分析:因为两个线程中用于通信的 Object 不是同一个对象,所以当线程2 调用 notify() 时,通知不到线程1.修改之后
public class Thread_1 extends Thread { Object object; public Thread_1(Object object) { this.object = object; } public void run() { System.out.println("线程1"); //线程1 进入等待 synchronized (object) { try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("线程_1 执行结束"); } } public class Thread_2 extends Thread { Object object; public Thread_2(Object object) { this.object = object; } public void run() { System.out.println("线程_2"); synchronized (object) { //线程_2 唤起 object.notify(); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程_2 执行结束"); } }
可以正常的唤起线程1,多次执行之后有时线程还是没发正常被唤起。
挂起(suspend) 和继续执行(resume) 线程
已经被废弃掉了。
不推荐使用 suspend() 去挂起线程的原因是, supend() 在导致线程暂停的同时并不会去释放任何锁资源。
如果 resume() 意外地在 suspend() 前执行,被挂起的线程很难有机会被继续执行。等待线程结束(join) 和谦让(yield)
一个线程的输入可能非常依赖于另外一个或者多个线程的输出,这个线程就需要等待依赖线程执行完毕
才能继续执行。 join() 操作实现这个功能。
public final void join() throws InterruptedException public final synchronized void join(long millis) throws InterruptedException
第一个表示无限等待,会一直阻塞当前线程。第二给出一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程会继续执行。
public class JoinMain { public volatile static int i = 0; public static class AddThread extends Thread { public void run() { for (i = 0;i < 1000000; i++) ; } } public static void main(String[] args) throws InterruptedException { AddThread addThread = new AddThread(); addThread.start(); //addThread.join(); System.out.println(i); } }
如果没有加入 join() 输出的为 0 或者其他的数,加入join() 输出 1000000join() 的本质是让调用线程 wait(). JDK 中 join() 实现的核心代码片段:
while(isAlive()) { wait(0); }
它让调用线程在当前线程对象上进行等待。当线程执行完后,被等待的线程会在退出前调用notifyAll().Thread.yield():
public static native void yield();
是一个静态方法,会使当前线程让出 CPU。当前线程在让出CPU后,还会进行CPU资源争夺。对于 Thread.yield() 好像在说,我已经完成一些最重要的工作了,可以休息下了。如果一个线程不那么重要,或者优先级非常低,又怕会占太多CPU,可以适当时候调用.
volatile 与 java 内存模型(JMM)
java 内存模型都是围绕 原子i型能性、有序性、可见性展开的。
当用 volatile 申明一个变量是,告诉虚拟机,这个变量极有可能被某些程序或线程修改。volatile 并不能代替锁,也无法保证一些复合操作的原子性。如下面,通过 volatile 是无法保证 i++ 原子性
public class VolataileMain { static volatile int i = 0; public static class PlushTask implements Runnable { @Override public void run() { for (int k = 0;k < 10000;k++) { i++; } } } public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for (int i = 0; i < 10;i++) { threads[i] = new Thread(new PlushTask()); threads[i].start(); } for (int i = 0;i<10;i++) { threads[i].join(); } System.out.println(i); } }
上面执行结果,可能会小于 100000。volatile 能保证数据的可见性和有序性。
public class NoVisibility { private static volatile boolean ready; private static int number; public static class ReaderThread extends Thread { public void run() { while (!ready) { System.out.println(number); } } } public static void main(String[] args) throws InterruptedException { new ReaderThread().start(); Thread.sleep(1000); number = 42; ready = true; Thread.sleep(1000); } }
当 ready 没用 volatile 申明,ready 值改变时线程是不会知道的。
0 0
- 高并发设置一
- 高并发TrafficServer设置
- 高并发设计方案一
- 高并发Java 一
- 高并发Java 一
- Linux 高并发环境设置
- nginx高并发处理设置
- Tomcat-高并发并设置
- Tomcat-高并发并设置
- 网站高并发(一)
- [高并发Java 一] 前言
- 【高并发Java一】前言
- [高并发Java 一] 前言
- 高并发 高流量网站 一
- 高并发网站开发问题总结一
- 高并发思路(一)-系统配置
- 高并发处理-初步了解(一)
- JAVA高并发学习笔记(一)
- java的初始化块、静态初始化块、构造函数的执行顺序及用途探究
- fingerprintd 编译进系统
- 紧急求助!ARM-GCC对于函数指针调用的编译有错误?【已经找到原因】
- 山东出差总结
- STM32学习之USART串口
- 高并发设置一
- 修改eclipe中tomcat发布目录
- 无处不在的内存泄漏-苹果BUG?
- Appium-3 AppiumXpath的用法
- MySQL合并数据和给表,字段取别名
- 堆和栈的区别 (转贴)
- TCP 三次握手 四次挥手
- 关于MultiDex
- [LeetCode]82. Remove Duplicates from Sorted List II