高并发设置一

来源:互联网 发布:思科log 端口 编辑:程序博客网 时间:2024/04/28 01:02
  1. 等待(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,多次执行之后有时线程还是没发正常被唤起。
  1. 挂起(suspend) 和继续执行(resume) 线程
    已经被废弃掉了。
    不推荐使用 suspend() 去挂起线程的原因是, supend() 在导致线程暂停的同时并不会去释放任何锁资源。
    如果 resume() 意外地在 suspend() 前执行,被挂起的线程很难有机会被继续执行。

  2. 等待线程结束(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,可以适当时候调用.
  1. 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