Java多线程与并发库高级应用

来源:互联网 发布:手机画图软件排行 编辑:程序博客网 时间:2024/05/21 08:33

Java 线程并发 名词解释

  1. Concurrent 同时
  2. Atomic 原子
  3. Callable 可调用
  4. Future 将来
  5. Condition 条件
  6. Reentrant 重入
  7. Semaphore 信号
  8. Signal 信号,信号量
  9. Cyclic 循环
  10. Barrier 屏障
  11. Latch 闩
  12. Exchanger 交换器
  13. Mutex 互斥

涉及内容

  1. 创建线程 new Thread();
  2. 创建定时器 new TimerTask();
  3. synchronized 关键字的使用
  4. ThreadLocal 的使用
  5. 多个线程间共享数据
  6. Java 原子性
  7. 创建线程池
  8. 线程执行完成的回调 Future 和 CompletionService
  9. 锁Lock
    1. 可重入的互斥锁 ReentrantLock
    2. 读写锁 ReentrantReadWriteLock
    3. Lock的 阻塞Condition
  10. Semaphore信号量
  11. CyclicBarrier循环阻塞
  12. CountdownLatch 非零0等待,0执行
  13. Exchanger线程间交换数据
  14. BlockingQueue 阻塞队列
  15. SynchronousQueue 阻塞同步队列
  16. 集合并发操作的ConcurrentModificationException

总结

  1. Lock 普通锁,与 synchronized 关键字功能相同,都是多线程互斥等待
  2. ReadWriteLock 读写锁,读与读并行,读与写互斥,写与写互斥
  3. Condition 条件互斥,与线程的 this.wait(); 和 this.notify(); 功能相同
  4. BoundedBuffer 使用 双Condition 完成 存与取 的阻塞
  5. Semaphore 信号量,比 Lock 更灵活
  6. CyclicBarrier 循环阻塞 只有当 指定数量的线程到达,才会继续执行
  7. CountdownLatch 非零0等待,0执行
  8. Exchanger 线程与线程间交换数据
  9. BlockingQueue 阻塞队列,队列满后阻塞,队列非满,按顺序插入

    阻塞队列

    阻塞队列

  10. SynchronousQueue 阻塞同步队列

传统方式创建一个线程

        // 1.        Thread thread = new Thread() {            /**             * 重写 run() 方法             */            @Override            public void run() {                while (true) {                    try {                        Thread.sleep(500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    // 获取当前线程名称                    System.out.println("1:" + Thread.currentThread().getName());                    // 获取当前线程名称 this 指当前线程                    System.out.println("2:" + this.getName());                }            }        };        thread.start();// 执行        // 2.        Thread thread2 = new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    try {                        Thread.sleep(500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println("1:" + Thread.currentThread().getName());                }            }        });        thread2.start();        // 3.        new Thread(                /**                 * 底层实现  在 run() 方法中执行 Runnable()                 */                new Runnable(){                    public void run() {                        while(true){                            try {                                Thread.sleep(500);                            } catch (InterruptedException e) {                                e.printStackTrace();                            }                            System.out.println("runnable :" + Thread.currentThread().getName());                        }                                               }                }            )// Thread 的方法参数        {            /**             * 重写父类的 run() 方法             * 此处没有调用父类的 run() 方法 ,所以上面的 Runnbale() 方法无法执行             */            @Override            public void run() {                while(true){                    try {                        Thread.sleep(500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println("thread :" + Thread.currentThread().getName());                }               }        }.start();

传统方式创建一个定时器

        // 输出  main() 方法 执行所在的线程        System.out.println("main() : "+Thread.currentThread().getName()); // main() : main        // 1. 创建一个 延迟 3s 的 Timer ,只执行一次        /*new Timer().schedule(new TimerTask() {            @Override            public void run() {                System.out.println("Timer 1: "+Thread.currentThread().getName()); // Timer 1: Timer-0                System.out.println("bombing");            }        }, 3000);*/        // 2. 创建一个 Timer 第一次延迟10s 执行,之后间隔 3s 执行         /*new Timer().schedule(new TimerTask() {            @Override            public void run() {                System.out.println("Timer 2: "+Thread.currentThread().getName()); // Timer 2: Timer-0                System.out.println("bombing!");            }        }, 10000, 3000);*/        // 3. 自定一个 TimerTask 实现 每隔 2s 执行一次        class MyTimerTask extends TimerTask{            @Override            public void run() {                /*                    Timer 没有循环利用,每次都是生成一个 新的 Timer                    Timer 3: Timer-0                    bombing!                    Timer 3: Timer-1                    bombing!                    Timer 3: Timer-2                    bombing!                    Timer 3: Timer-3                    bombing!                    Timer 3: Timer-4                    bombing!                    Timer 3: Timer-5                    bombing!                    Timer 3: Timer-6                    bombing!                    Timer 3: Timer-7                    bombing!                    Timer 3: Timer-8                    bombing!                    Timer 3: Timer-9                    bombing!                    Timer 3: Timer-10                    bombing!                    ...                */                System.out.println("Timer 3: "+Thread.currentThread().getName());                System.out.println("bombing!");                // TimerTask 内部 在调用 Timer() 执行自己                new Timer().schedule(/*new TimerTask() {                    @Override                    public void run() {                        System.out.println("bombing!");                        // 此处只执行一次,如果需要实现每个 2s 执行一次,                        // 需要 再 启动一个 Timer                        //new Timer().schedule(new TimerTask(){}, 2000);                    }                }*/new MyTimerTask(),2000);//类似 递归方式 ,new 一个 TimerTask()            }        }        // 入口 Timer()        new Timer().schedule(new MyTimerTask(), 2000);
  1. 开源框架:基于 Quartz 开发企业级任务调度应用
    1. 案例:工作日发送邮件,周末休息

传统的 线程互斥技术

public static void main(String[] args) {        // 静态方法访问 内部类 无法编译通过,编译器报错        // 因为 内部类 共享外部类的 成员变量和方法,静态方法创建时,外部类的对象并未创建,这与内部类的定义相矛盾        // 使用对象方法 包装 内部类        new _3_TraditionalThreadSynchronized().init();    }    private void init() {        final Outputer outputer = new Outputer();        new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    outputer.output("zhangxiaoxiang");                }            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                while (true) {                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    // outputer.output2("lihuoming");                    // outputer.output3("lihuoming");                }            }        }).start();    }    static class Outputer {        public void output(String name) {            int len = name.length();            // synchronized (this) // 此时与 output2 生成互斥锁,互斥对象是 当前类            synchronized (Outputer.class) // 此时与 output3 生成互斥锁,互斥对象是 类对象            {                for (int i = 0; i < len; i++) {                    System.out.print(name.charAt(i));                }                System.out.println();            }        }        /**         * 互斥锁 为 synchronized (this)         * @param name         */        public synchronized void output2(String name) {            int len = name.length();            for (int i = 0; i < len; i++) {                System.out.print(name.charAt(i));            }            System.out.println();        }        /**         * 互斥锁 为 synchronized (Outputer.class)          * @param name         */        public static synchronized void output3(String name) {            int len = name.length();            for (int i = 0; i < len; i++) {                System.out.print(name.charAt(i));            }            System.out.println();        }    }

传统的线程间通讯

 public class _4_TraditionalThreadCommunication {    public static void main(String[] args) {        // 1. 主线程 和 子线程 分别 执行 从 0 - 9 不可被打断,各执行 50 次        /* new Thread(new Runnable() {            @Override            public void run() {                synchronized (ExampleUnitTest.class) {                    for (int i = 0; i < 50; i++) {                        for (int j = 0; j < 10; j++) {                            System.out.println("sub i:" + i + " j:" + j);                        }                    }                }            }        }).start();        synchronized (ExampleUnitTest.class) {            for (int i = 0; i < 50; i++) {                for (int j = 0; j < 10; j++) {                    System.out.println("main i:" + i + " j:" + j);                }            }        }*/        // 2. 子线程 执行 10次,主线程执行 100 次,交替执行 50次,中间不被打断        /*final Business business = new Business();        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 1; i <= 50; i++) {                    business.sub(i);                }            }        }).start();        for (int i = 1; i <= 50; i++) {            business.main(i);        }*/    }    static class Business {        private boolean bShouldSub = true;// 控制是否是子线程        public synchronized void sub(int i) {            // if(!bShouldSub) // 如果使用 if 可能会出现 伪唤醒,while 比 if 精确。原因:if 语句只会执行一次,如果被notify()但是条件并没有满足,后续代码就会执行,出现错误。while 会判断条件是否满足            while (!bShouldSub) {// 如果主线程在执行,bShouldSub = false,进入循环,当前线程 wait()                try {                    this.wait();// 等待                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            // 执行            for (int j = 0; j < 10; j++) {                System.out.println("sub i:" + i + " j:" + j);            }            // 执行完成            bShouldSub = false;            // 唤醒等待的 wait() 的线程            this.notify();        }        public synchronized void main(int i) {            // if(bShouldSub) // 如果使用 if 可能会出现 伪唤醒,while 比 if 精确。原因:if 语句只会执行一次,如果被notify()但是条件并没有满足,后续代码就会执行,出现错误。while 会判断条件是否满足            while (bShouldSub) {// 如果主线程在执行,bShouldSub = true ,进入循环,主线程 wait();                try {                    this.wait();// 等待                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            // 执行            for (int j = 0; j < 100; j++) {                System.out.println("main i:" + i + " j:" + j);            }            // 执行完成            bShouldSub = true;            // 唤醒等待的 wait() 的线程            this.notify();        }    }    /**     * 这种做法 无法实现,需要 手动去切换执行线程,废弃     *      * @author Wjz     *      */    static class Business2 {        private boolean bShouldSub = true;        public synchronized void sub(int i) {            if (bShouldSub)             {                // 执行                for (int j = 0; j < 10; j++) {                    System.out.println("sub i:" + i + " j:" + j);                }                bShouldSub = false;            }        }        public synchronized void main(int i) {            if (!bShouldSub)             {// 执行                for (int j = 0; j < 100; j++) {                    System.out.println("main i:" + i + " j:" + j);                }                bShouldSub = true;            }        }    }}

线程范围共享变量

    // 1. HashMap 方式,使用 Thread 对象 作为 key    private static Map<Thread, Integer> threadData = new HashMap<Thread, Integer>();    public static void main(String[] args) {        for(int i=0;i<2;i++){            new Thread(new Runnable(){                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName()                             + " has put data :" + data);                    threadData.put(Thread.currentThread(), data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A{        public void get(){            int data = threadData.get(Thread.currentThread());            System.out.println("A from " + Thread.currentThread().getName()                     + " get data :" + data);        }    }    static class B{        public void get(){            int data = threadData.get(Thread.currentThread());                      System.out.println("B from " + Thread.currentThread().getName()                     + " get data :" + data);        }           }    // 2. ThreadLocal 方式    private static ThreadLocal<Integer> x = new ThreadLocal<Integer>();    public static void main(String[] args) {        for(int i=0;i<2;i++){            new Thread(new Runnable(){                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName()                             + " has put data :" + data);                    x.set(data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A{        public void get(){            int data = x.get();            System.out.println("A from " + Thread.currentThread().getName()                     + " get data :" + data);        }    }    static class B{        public void get(){            int data = x.get();                 System.out.println("B from " + Thread.currentThread().getName()                     + " get data :" + data);        }           }    // 3. 优雅的 ThreadLocal 方式    // 普通方式:ThreadLocal 暴露在调用方    // 高雅方式:将 ThreadLocal 封装到使用方    private static ThreadLocal<MyThreadScopeData> tData= new ThreadLocal<MyThreadScopeData>();    public static void main(String[] args) {        for (int i = 0; i < 2; i++) {            new Thread(new Runnable() {                @Override                public void run() {                    int data = new Random().nextInt();                    System.out.println(Thread.currentThread().getName()                            + " has put data :" + data);                    /*                                       1. 普通方式                     MyThreadScopeData myData = new MyThreadScopeData();                     myData.setName("name" + data);                     myData.setAge(data);                     tData.set(myData);                    */                    // 2. 高级优雅方式                    MyThreadScopeData.getThreadInstance().setName("name" + data);                    MyThreadScopeData.getThreadInstance().setAge(data);                    new A().get();                    new B().get();                }            }).start();        }    }    static class A {        public void get() {            /*                   1. 普通方式                 MyThreadScopeData myData = myThreadScopeData.get();;             System.out.println("A from " + Thread.currentThread().getName()                                 + " getMyData: " + myData.getName() + "," +                                myData.getAge());            */            // 2. 高级优雅方式            MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();            System.out                    .println("A from " + Thread.currentThread().getName()                            + " getMyData: " + myData.getName() + ","                            + myData.getAge());        }    }    static class B {        public void get() {            MyThreadScopeData myData = MyThreadScopeData.getThreadInstance();            System.out                    .println("B from " + Thread.currentThread().getName()                            + " getMyData: " + myData.getName() + ","                            + myData.getAge());        }    }}/** * 在当前类中 封装 ThreadLocal *  * @author Wjz *  */class MyThreadScopeData {    private MyThreadScopeData() {    }    /**     * private static MyThreadScopeData instance = null; 饥汉 模式  //new MyThreadScopeData(); 饱汉 模式     */    private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();    /**     * 每个线程都有独立的 ThreadLocal 因此不需要 同步     *      * @return     */    public static/*synchronized*/MyThreadScopeData getThreadInstance() {        MyThreadScopeData instance = map.get();        if (instance == null) {            instance = new MyThreadScopeData();            map.set(instance);        }        return instance;    }    private String name;    private int age;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }

多个线程之间共享数据

public class _8_MultiThreadShareData {    private int j;    public static void main(String[] args) {        // 设计4个线程,其中两个线程每次对j增加1,各100次,另外两个线程对j每次减1,各100次。        // 以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。        _8_MultiThreadShareData _8 = new _8_MultiThreadShareData();        Inc inc = _8.new Inc();        Dec dec = _8.new Dec();        for (int i = 0; i < 2; i++) {            Thread thread = new Thread(inc);            thread.start();            thread = new Thread(dec);            thread.start();        }    }    /**     * 需要多个线程同时访问,增加 同步关键字     */    private synchronized void inc() {        j++;        System.out.println(Thread.currentThread().getName()+" -inc: "+j);    }    /**     * 需要多个线程同时访问,增加 同步关键字     */    private void dec(){        j--;        System.out.println(Thread.currentThread().getName()+" -dec: "+j);    }    class Inc implements Runnable{        @Override        public void run() {            for(int i=0;i<100;i++){                inc();            }        }    }    class Dec implements Runnable{        @Override        public void run() {            for(int i=0;i<100;i++){                dec();            }        }    }}
public class _9_MultiThreadShareData2 {    // 方法一,静态成员对象    private static ShareData1 data1 = new ShareData1();    public static void main(String[] args) {        // 1. 方法一        final ShareData1 data1 = new ShareData1();        new Thread(new Runnable() {            @Override            public void run() {                data1.decrement();            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                data1.increment();            }        }).start();        // 2. 方法二 传递对象 到具体的逻辑对象        ShareData1 data2 = new ShareData1();        new Thread(new MyRunnable1(data2)).start();        new Thread(new MyRunnable2(data2)).start();    }}/** * 传递对象,实现 减法 操作 *  * @author Wjz *  */class MyRunnable1 implements Runnable {    private ShareData1 data1;    public MyRunnable1(ShareData1 data1) {        this.data1 = data1;    }    public void run() {        data1.decrement();    }}/** * 传递对象,实现 加法 操作 *  * @author Wjz *  */class MyRunnable2 implements Runnable {    private ShareData1 data1;    public MyRunnable2(ShareData1 data1) {        this.data1 = data1;    }    public void run() {        data1.increment();    }}class ShareData1 /*implements Runnable*/{    /*      private int count = 100;            @Override            public void run() {                while(true){                    count--;                }            }*/    private int j = 0;    public synchronized void increment() {        j++;    }    public synchronized void decrement() {        j--;    }}

Java 线程原子性操作

Atomic

所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。

Atomic

Java 线程池

        // ExecutorService threadPool = Executors.newFixedThreadPool(3);        // ExecutorService threadPool = Executors.newCachedThreadPool();        ExecutorService threadPool = Executors.newSingleThreadExecutor();        for (int i = 1; i <= 10; i++) {            final int task = i;            threadPool.execute(new Runnable() {                @Override                public void run() {                    for (int j = 1; j <= 10; j++) {                        try {                            Thread.sleep(20);                        } catch (InterruptedException e) {                                  e.printStackTrace();                        }                        System.out.println(Thread.currentThread().getName()                                + " is looping of " + j + " for  task of "                                + task);                    }                }            });        }        System.out.println("all of 10 tasks have committed! ");        // 关闭线程        // threadPool.shutdown();        // threadPool.shutdownNow();        Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                System.out.println("bombing!");            }        }, 6, 2, TimeUnit.SECONDS);

Java线程完成回调 Callable与Future和CompletionService

// Callable -> Future        ExecutorService threadPool = Executors.newSingleThreadExecutor();        Future<String> future = threadPool.submit(new Callable<String>() {            public String call() throws Exception {                Thread.sleep(2000);                return "hello";            };        });        System.out.println("等待结果");        try {            // 10s 就要收到回调结果,否则报 TimeoutException            System.out.println("拿到结果:" + future.get(10, TimeUnit.SECONDS));            // 一直等待回调结果            // System.out.println("拿到结果:" + future.get());        } catch (InterruptedException e1) {            e1.printStackTrace();        } catch (ExecutionException e1) {            e1.printStackTrace();        } catch (TimeoutException e1) {            e1.printStackTrace();        }        // Multi Callable -> Multi CompletionService        ExecutorService threadPool2 = Executors.newFixedThreadPool(10);        CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);        for (int i = 1; i <= 10; i++) {            final int seq = i;            completionService.submit(new Callable<Integer>() {                @Override                public Integer call() throws Exception {                    Thread.sleep(new Random().nextInt(5000));                    return seq;                }            });        }        for (int i = 0; i < 10; i++) {            try {                System.out.println(completionService.take().get());            } catch (InterruptedException e) {                e.printStackTrace();            } catch (ExecutionException e) {                e.printStackTrace();            }        }    }

Java 线程锁 Lock

与 synchronized 效果相同,Lock 更加面向对象

public static void main(String[] args) {        new _12_Lock().init();    }    private void init(){        final Outputer outputer = new Outputer();        new Thread(new Runnable(){            @Override            public void run() {                while(true){                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    outputer.output("zhangxiaoxiang");                }            }        }).start();        new Thread(new Runnable(){            @Override            public void run() {                while(true){                    try {                        Thread.sleep(10);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    outputer.output("lihuoming");                }            }        }).start();    }    static class Outputer{        /**         * synchronized 关键字效果 相同         * ReentrantLock: Lock 接口的实现类         */        Lock lock = new ReentrantLock();        public void output(String name){            int len = name.length();            lock.lock();            try{                for(int i=0;i<len;i++){                    System.out.print(name.charAt(i));                }                System.out.println();            }finally{                // 上锁后 如果抛异常 需要被被释放                lock.unlock();            }        }    }

Java 读写锁 ReentrantReadWriteLock()

public class _13_ReadWriteLock {    public static void main(String[] args) {        // 自定义Queue3对象        final Queue3 q3 = new Queue3();        for(int i=0;i<3;i++)        {            new Thread(){                public void run(){                    while(true){                        q3.get();                                           }                }            }.start();            new Thread(){                public void run(){                    while(true){                        q3.put(new Random().nextInt(10000));                    }                }                       }.start();        }    }}class Queue3{    //共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。    private Object data = null;    ReadWriteLock rwl = new ReentrantReadWriteLock();    /**     * 读数据     */    public void get(){        rwl.readLock().lock();        try {            System.out.println(Thread.currentThread().getName() + " be ready to read data!");            Thread.sleep((long)(Math.random()*1000));            System.out.println(Thread.currentThread().getName() + "have read data :" + data);                   } catch (InterruptedException e) {            e.printStackTrace();        }finally{            rwl.readLock().unlock();        }    }    /**     * 写数据     * @param data     */    public void put(Object data){        rwl.writeLock().lock();        try {            System.out.println(Thread.currentThread().getName() + " be ready to write data!");                              Thread.sleep((long)(Math.random()*1000));            this.data = data;                   System.out.println(Thread.currentThread().getName() + " have write data: " + data);                         } catch (InterruptedException e) {            e.printStackTrace();        }finally{            rwl.writeLock().unlock();        }    }}
// 官方案例 读取缓存数据 伪代码class CachedData {    Object data;    volatile boolean cacheValid;    ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();    void processCachedData() {        rwl.readLock().lock();        if (!cacheValid) {            // Must release read lock before acquiring write lock            rwl.readLock().unlock();            rwl.writeLock().lock();             // 如果多个线程同时阻塞在此处,等一个线程完成,需要更新状态,否则其他线程依然会进入            // Recheck state because another thread might have acquired            //   write lock and changed state before we did.            if (!cacheValid) {              data = ...              cacheValid = true;// 更新状态            }            // Downgrade by acquiring read lock before releasing write lock            // 在释放写入锁定之前通过获取读取锁定进行降级            // 写锁降级,降级更新锁            rwl.readLock().lock();            rwl.writeLock().unlock(); // Unlock write, still hold read         }         use(data);         rwl.readLock().unlock();    } }

Java 阻塞Condition

/** * 与 _4_TraditionalThreadCommunication  * 使用 synchronized  * this.wait(); * this.notify(); * 功能相同 * @author Wjz * */public class _14_ConditionCommunication {    public static void main(String[] args) {        final Business business = new Business();        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 1; i <= 50; i++) {                    business.sub(i);                }            }        }).start();        for (int i = 1; i <= 50; i++) {            business.main(i);        }    }    /**     * 静态内部类 _14_ConditionCommunication.Business      * 外部类 Business 包名相同会冲突     *      * @author Wjz     *      */    static class Business {        Lock lock = new ReentrantLock();        Condition condition = lock.newCondition();        private boolean bShouldSub = true;        public void sub(int i) {            lock.lock();            try {                while (!bShouldSub) {                    try {                        condition.await();                    } catch (Exception e) {                        e.printStackTrace();                    }                }                for (int j = 1; j <= 10; j++) {                    System.out.println("sub thread sequence of " + j                            + ",loop of " + i);                }                bShouldSub = false;                condition.signal();            } finally {                lock.unlock();            }        }        public void main(int i) {            lock.lock();            try {                while (bShouldSub) {                    try {                        condition.await();                    } catch (Exception e) {                        e.printStackTrace();                    }                }                for (int j = 1; j <= 100; j++) {                    System.out.println("main thread sequence of " + j                            + ",loop of " + i);                }                bShouldSub = true;                condition.signal();            } finally {                lock.unlock();            }        }    }}
/** * 阻塞式队列的实现原理 * @author Wjz * */public class _15_BoundedBuffer {    final Lock lock = new ReentrantLock();    final Condition notFull = lock.newCondition();    final Condition notEmpty = lock.newCondition();    // Buffer 总长度    final Object[] items = new Object[100];    int putptr, takeptr, count;    /**     * 存入数据     * @param x     * @throws InterruptedException     */    public void put(Object x) throws InterruptedException {        lock.lock();        try {            while (count == items.length)// 已满                notFull.await();            items[putptr] = x;            if (++putptr == items.length)                putptr = 0;            ++count;            notEmpty.signal();// 非空唤醒        } finally {            lock.unlock();        }    }    /**     * 取出数据     * @return     * @throws InterruptedException     */    public Object take() throws InterruptedException {        lock.lock();        try {            while (count == 0)// 已空                notEmpty.await();            Object x = items[takeptr];            if (++takeptr == items.length)                takeptr = 0;            --count;            notFull.signal();// 非满唤醒            return x;        } finally {            lock.unlock();        }    }}
/** * 根据 _14_ConditionCommunication 案例 增加多个线程间通讯 *  * @author Wjz *  */public class _16_MultiConditionCommunication {    public static void main(String[] args) {        final Business business = new Business();        // 子线程 1        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 1; i <= 50; i++) {                    business.sub2(i);                }            }        }).start();        // 子线程 2        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 1; i <= 50; i++) {                    business.sub3(i);                }            }        }).start();        // 主线程        for (int i = 1; i <= 50; i++) {            business.main(i);        }    }    static class Business {        Lock lock = new ReentrantLock();        Condition condition1 = lock.newCondition();// 主线程的条件控制锁        Condition condition2 = lock.newCondition();// 子线程1的条件控制锁        Condition condition3 = lock.newCondition();// 子线程2的条件控制锁        private int shouldSub = 1;//  断点记录         public void sub2(int i) {            lock.lock();            try {                while (shouldSub != 2) {                    try {                        condition2.await();                    } catch (Exception e) {                        e.printStackTrace();                    }                }                for (int j = 1; j <= 10; j++) {                    System.out.println("sub2 thread sequence of " + j                            + ",loop of " + i);                }                // 线程2唤醒线程3                shouldSub = 3;                condition3.signal();            } finally {                lock.unlock();            }        }        public void sub3(int i) {            lock.lock();            try {                while (shouldSub != 3) {                    try {                        condition3.await();                    } catch (Exception e) {                        e.printStackTrace();                    }                }                for (int j = 1; j <= 20; j++) {                    System.out.println("sub3 thread sequence of " + j                            + ",loop of " + i);                }                // 线程2唤醒主线程                shouldSub = 1;                condition1.signal();            } finally {                lock.unlock();            }        }        public void main(int i) {            lock.lock();            try {                while (shouldSub != 1) {                    try {                        condition1.await();                    } catch (Exception e) {                        e.printStackTrace();                    }                }                for (int j = 1; j <= 100; j++) {                    System.out.println("main thread sequence of " + j                            + ",loop of " + i);                }                // 主线程唤醒线程2                shouldSub = 2;                condition2.signal();            } finally {                lock.unlock();            }        }    }}

Java 线程Semaphore信号量

比 Lock + Condition 灵活

public class _17_Semaphore {    public static void main(String[] args) {        ExecutorService service = Executors.newCachedThreadPool();        final Semaphore sp = new Semaphore(3);        for (int i = 0; i < 10; i++) {            Runnable runnable = new Runnable() {                public void run() {                    try {                        // 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。                        sp.acquire();                    } catch (InterruptedException e1) {                        e1.printStackTrace();                    }                    System.out.println("线程" + Thread.currentThread().getName()                            + "进入,当前已有" + (3 - sp.availablePermits()) + "个并发");                    try {                        Thread.sleep((long) (Math.random() * 10000));                    } catch (InterruptedException e) {                        e.printStackTrace();                    }finally{                        System.out.println("线程" + Thread.currentThread().getName()                            + "即将离开");                        // 释放一个许可,将其返回给信号量。                        sp.release();                    }                    // 下面代码有时候执行不准确,因为其没有和上面的代码合成 原子 单元                    System.out.println("线程" + Thread.currentThread().getName()                            + "已离开,当前已有" + (3 - sp.availablePermits()) + "个并发");                }            };            // newCachedThreadPool 会创建10个线程并发            service.execute(runnable);            /*线程pool-1-thread-1进入,当前已有3个并发线程pool-1-thread-2进入,当前已有3个并发线程pool-1-thread-3进入,当前已有3个并发线程pool-1-thread-1即将离开线程pool-1-thread-1已离开,当前已有2个并发线程pool-1-thread-4进入,当前已有3个并发线程pool-1-thread-2即将离开线程pool-1-thread-2已离开,当前已有2个并发线程pool-1-thread-5进入,当前已有3个并发线程pool-1-thread-5即将离开线程pool-1-thread-5已离开,当前已有2个并发线程pool-1-thread-8进入,当前已有3个并发线程pool-1-thread-8即将离开线程pool-1-thread-8已离开,当前已有2个并发线程pool-1-thread-6进入,当前已有3个并发线程pool-1-thread-3即将离开线程pool-1-thread-3已离开,当前已有2个并发线程pool-1-thread-10进入,当前已有3个并发线程pool-1-thread-4即将离开线程pool-1-thread-4已离开,当前已有2个并发线程pool-1-thread-7进入,当前已有3个并发线程pool-1-thread-10即将离开线程pool-1-thread-10已离开,当前已有2个并发线程pool-1-thread-9进入,当前已有3个并发线程pool-1-thread-7即将离开线程pool-1-thread-7已离开,当前已有2个并发线程pool-1-thread-6即将离开线程pool-1-thread-6已离开,当前已有1个并发线程pool-1-thread-9即将离开线程pool-1-thread-9已离开,当前已有0个并发              */        }    }}

Java 线程 循环阻塞

public class _18_CyclicBarrier {    public static void main(String[] args) {        ExecutorService service = Executors.newCachedThreadPool();        final  CyclicBarrier cb = new CyclicBarrier(3);        for(int i=0;i<3;i++){            Runnable runnable = new Runnable(){                    public void run(){                    try {                        Thread.sleep((long)(Math.random()*10000));                          System.out.println("线程" + Thread.currentThread().getName() +                                 "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                                               // 阻塞1,只有当3个线程同时到达,才会继续向下                        cb.await();                        Thread.sleep((long)(Math.random()*10000));                          System.out.println("线程" + Thread.currentThread().getName() +                                 "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                        // 阻塞2, 只有当3个线程同时到达,才会继续向下                        cb.await();                         Thread.sleep((long)(Math.random()*10000));                          System.out.println("线程" + Thread.currentThread().getName() +                                 "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                                             // 阻塞3,只有当3个线程同时到达,才会继续向下                        cb.await();                                         } catch (Exception e) {                        e.printStackTrace();                    }                               }            };            service.execute(runnable);        }        service.shutdown();    }}

Java 线程 CountdownLatch

public class _19_CountdownLatch {    public static void main(String[] args) {        ExecutorService service = Executors.newCachedThreadPool();        final CountDownLatch cdOrder = new CountDownLatch(1); // 主线程控制,为0 继续向下执行,初始化为1        final CountDownLatch cdAnswer = new CountDownLatch(3); // 子线程控制,为0 继续向下执行,初始化为3        for (int i = 0; i < 3; i++) {            Runnable runnable = new Runnable() {                public void run() {                    try {                        System.out.println("线程"                                + Thread.currentThread().getName() + "正准备接受命令");                        // 等待主线程控制 -1                        cdOrder.await();                        System.out.println("线程"                                + Thread.currentThread().getName() + "已接受命令");                        Thread.sleep((long) (Math.random() * 10000));                        System.out                                .println("线程"                                        + Thread.currentThread().getName()                                        + "回应命令处理结果");                        // cdAnswer -1                        cdAnswer.countDown();                    } catch (Exception e) {                        e.printStackTrace();                    }                }            };            service.execute(runnable);        }        try {            Thread.sleep((long) (Math.random() * 10000));            System.out.println("线程" + Thread.currentThread().getName()                    + "即将发布命令");            cdOrder.countDown();            System.out.println("线程" + Thread.currentThread().getName()                    + "已发送命令,正在等待结果");            // 等待 3个 子线程 -1            cdAnswer.await();            System.out.println("线程" + Thread.currentThread().getName()                    + "已收到所有响应结果");        } catch (Exception e) {            e.printStackTrace();        }        service.shutdown();        /*线程pool-1-thread-1正准备接受命令线程pool-1-thread-3正准备接受命令线程pool-1-thread-2正准备接受命令线程main即将发布命令线程main已发送命令,正在等待结果线程pool-1-thread-1已接受命令线程pool-1-thread-2已接受命令线程pool-1-thread-3已接受命令线程pool-1-thread-3回应命令处理结果线程pool-1-thread-1回应命令处理结果线程pool-1-thread-2回应命令处理结果线程main已收到所有响应结果         */    }}

Java 线程 Exchanger

public class _20_Exchanger {    public static void main(String[] args) {        ExecutorService service = Executors.newCachedThreadPool();        final Exchanger exchanger = new Exchanger();        service.execute(new Runnable() {            public void run() {                try {                    String data1 = "zxx";                    System.out.println("线程" + Thread.currentThread().getName()                            + "正在把数据" + data1 + "换出去");                    Thread.sleep((long) (Math.random() * 10000));                    String data2 = (String) exchanger.exchange(data1);                    System.out.println("线程" + Thread.currentThread().getName()                            + "换回的数据为" + data2);                } catch (Exception e) {                }            }        });        service.execute(new Runnable() {            public void run() {                try {                    String data1 = "lhm";                    System.out.println("线程" + Thread.currentThread().getName()                            + "正在把数据" + data1 + "换出去");                    Thread.sleep((long) (Math.random() * 10000));                    String data2 = (String) exchanger.exchange(data1);                    System.out.println("线程" + Thread.currentThread().getName()                            + "换回的数据为" + data2);                } catch (Exception e) {                }            }        });        /*线程pool-1-thread-1正在把数据zxx换出去线程pool-1-thread-2正在把数据lhm换出去线程pool-1-thread-1换回的数据为lhm线程pool-1-thread-2换回的数据为zxx         */    }}

Java 多线程 BlockingQueue 阻塞队列

// BlockingQueue 阻塞队列 的使用public class _21_BlockingQueue {    public static void main(String[] args) {        /*Thread-1准备放数据!Thread-1已经放了数据,队列目前有1个数据Thread-0准备放数据!Thread-0已经放了数据,队列目前有2个数据Thread-1准备放数据!Thread-1已经放了数据,队列目前有3个数据Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-0准备放数据!Thread-0已经放了数据,队列目前有3个数据Thread-1准备放数据!Thread-0准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-1已经放了数据,队列目前有3个数据Thread-1准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-0已经放了数据,队列目前有3个数据Thread-0准备放数据!Thread-2准备取数据!Thread-2已经取走数据,队列目前有2个数据Thread-1已经放了数据,队列目前有3个数据          */        final BlockingQueue queue = new ArrayBlockingQueue(3);        for(int i=0;i<2;i++){            new Thread(){                public void run(){                    while(true){                        try {                            Thread.sleep((long)(Math.random()*1000));                            System.out.println(Thread.currentThread().getName() + "准备放数据!");                                                        queue.put(1);                            // 非原子性语句,可能不打印                            System.out.println(Thread.currentThread().getName() + "已经放了数据," +                                                                   "队列目前有" + queue.size() + "个数据");                        } catch (InterruptedException e) {                            e.printStackTrace();                        }                    }                }            }.start();        }        new Thread(){            public void run(){                while(true){                    try {                        //将此处的睡眠时间分别改为100和1000,观察运行结果                        Thread.sleep(1000);                        System.out.println(Thread.currentThread().getName() + "准备取数据!");                        queue.take();                        // 非原子性语句,可能不打印                        System.out.println(Thread.currentThread().getName() + "已经取走数据," +                                                           "队列目前有" + queue.size() + "个数据");                                        } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }.start();              }}
/** * 使用 阻塞队列 完成 _4_TraditionalThreadCommunication 案例 *  * @author Wjz *  */public class _22_BlockingQueueCommunication {    public static void main(String[] args) {        final Business business = new Business();        new Thread(new Runnable() {            @Override            public void run() {                for (int i = 1; i <= 50; i++) {                    business.sub(i);                }            }        }).start();        for (int i = 1; i <= 50; i++) {            business.main(i);        }    }    static class Business {        BlockingQueue<Integer> queue1 = new ArrayBlockingQueue<Integer>(1);// 初始化为1        BlockingQueue<Integer> queue2 = new ArrayBlockingQueue<Integer>(1);// 初始化为1        // 匿名构造方法,优先于任意构造方法。每个构造方法初始化一次,匿名构造方法也跟着初始化        /*static 静态代码块,只在类初始化的时候执行一次*/        {            try {                queue2.put(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        public void sub(int i) {            try {                queue1.put(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            for (int j = 1; j <= 10; j++) {                System.out.println("sub thread sequece of " + j + ",loop of "                        + i);            }            try {                queue2.take();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        public void main(int i) {            try {                queue2.put(1);            } catch (InterruptedException e1) {                e1.printStackTrace();            }            for (int j = 1; j <= 100; j++) {                System.out.println("main thread sequece of " + j + ",loop of "                        + i);            }            try {                queue1.take();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

Java 多线程 SynchronousQueue 阻塞同步队列

  1. 一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然。
  2. 同步队列没有任何内部容量,甚至连一个队列的容量都没有。

Java 多线程 集合并发操作的ConcurrentModificationException

public class _23_CollectionModifyException {    public static void main(String[] args) {        Collection users =        // new CopyOnWriteArrayList();        new ArrayList();        users.add(new User("张三", 28));        users.add(new User("李四", 25));        users.add(new User("王五", 31));        Iterator itrUsers = users.iterator();        while (itrUsers.hasNext()) {            System.out.println("aaaa");            User user = (User) itrUsers.next();            if ("王五".equals(user.getName())) {                // 直接修改集合 会报错                 users.remove(user);                // 修改迭代器,正常                //itrUsers.remove();            } else {                System.out.println(user);            }        }        System.out.println("当前集合大小:"+users.size());    }}class User implements Cloneable {    private String name;    private int age;    public User(String name, int age) {        this.name = name;        this.age = age;    }    public boolean equals(Object obj) {        if (this == obj) {            return true;        }        if (!(obj instanceof User)) {            return false;        }        User user = (User) obj;        // if(this.name==user.name && this.age==user.age)        if (this.name.equals(user.name) && this.age == user.age) {            return true;        } else {            return false;        }    }    public int hashCode() {        return name.hashCode() + age;    }    public String toString() {        return "{name:'" + name + "',age:" + age + "}";    }    public Object clone() {        Object object = null;        try {            object = super.clone();        } catch (CloneNotSupportedException e) {        }        return object;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }}
阅读全文
0 0
原创粉丝点击