• Java 多线程案例


    同步代码块

    SynchronizedTest类,用来表示取票功能

    package concurency.chapter6;
    
    public class SynchronizedTest implements Runnable {
        public static final int MAX = 250;
    
        private int index = 0;
    
        @Override
        public void run() {
            while(true) {
                if(ticket())
                    break;
            }
        }
    
        // synchronized 此时锁的是 this 锁的是一个对象,别弄错了
        private synchronized boolean ticket() {
            if(index >= MAX)
                return true;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " " + (++index));
            return false;
        }
    }
    

    Ticket 模拟游乐园放票

    package concurency.chapter6;
    
    public class Ticket {
        public static void main(String[] args) {
            final SynchronizedTest synRunnable = new SynchronizedTest();
            Thread t1 = new Thread(synRunnable, "窗口1");
            Thread t2 = new Thread(synRunnable, "窗口2");
            Thread t3 = new Thread(synRunnable, "窗口3");
            t1.start(); t2.start(); t3.start();
        }
    }
    

    synchronized 同步方法时,其实是同步的this对象

    下面可以证明

    package concurency.chapter6;
    
    public class SynchronizedThis {
        public static void main(String[] args) {
            LockThis l1 = new LockThis();
            new Thread("thread1"){
                @Override
                public void run() {
                    l1.m1();
                }
            }.start();
    
            new Thread("thread2"){
                @Override
                public void run() {
                    l1.m2();
                }
            }.start();
        }
    }
    
    class LockThis {
        public synchronized void m1() {
            try {
                System.out.println(Thread.currentThread().getName() + " method1");
                Thread.sleep(3_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public synchronized void m2() {
            try {
                System.out.println(Thread.currentThread().getName() + " method2");
                Thread.sleep(3_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    synchronized 同步静态方法时,其实是同步的class

    package concurency.chapter6;
    
    public class SynchronizedThis {
        public static void main(String[] args) {
            new Thread("thread1"){
                @Override
                public void run() {
                    LockThis.m1();
                }
            }.start();
    
            new Thread("thread2"){
                @Override
                public void run() {
                    LockThis.m2();
                }
            }.start();
        }
    }
    
    class LockThis {
        public static synchronized void m1() {
            try {
                System.out.println(Thread.currentThread().getName() + " method1");
                Thread.sleep(3_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static synchronized void m2() {
            try {
                System.out.println(Thread.currentThread().getName() + " method2");
                Thread.sleep(3_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    死锁小案例

    Service1 两个方法. m1和m2

    package concurency.chapter7;
    
    public class Service1 {
    
        private final Object lock1 = new Object();
    
        public Service2 service2;
    
        public Service1(Service2 service2) {
            this.service2 = service2;
        }
    
        public void m1() {
            synchronized(lock1) {
                System.out.println("---m1---");
                service2.s1();
            }
        }
    
        public void m2() {
            synchronized(lock1) {
                System.out.println("---m2---");
            }
        }
    }
    

    Service2 两个方法, s1和s2

    package concurency.chapter7;
    
    public class Service2 {
        public void s1() {
            synchronized (lock2) {
                System.out.println("---s1---");
            }
        }
    
        public void s2() {
            synchronized (lock2) {
                System.out.println("---s2---");
                service1.m2();
            }
        }
    
        private final Object lock2 = new Object();
    
        public Service1 service1;
    
        void setService1(Service1 service1) {
            this.service1 = service1;
        }
    }
    

    死锁尝试

    package concurency.chapter7;
    
    public class DeadLockTest {
        public static void main(String[] args) {
            Service2 service2 = new Service2();
            Service1 service1 = new Service1(service2);
            service2.setService1(service1);
    
            new Thread() {
                @Override
                public void run() {
                    while(true)
                        service2.s2();
                }
            }.start();
    
            new Thread() {
                @Override
                public void run() {
                    while(true)
                        service1.m1();
                }
            }.start();
        }
    }
    

    jstack命令查看线程

    Found one Java-level deadlock:
    =============================
    "Thread-1":
      waiting to lock monitor 0x0000000017ceddd8 (object 0x00000000d5f7e150, a java.lang.Object),
      which is held by "Thread-0"
    "Thread-0":
      waiting to lock monitor 0x0000000017cec938 (object 0x00000000d5f806c8, a java.lang.Object),
      which is held by "Thread-1"
    
    Java stack information for the threads listed above:
    ===================================================
    "Thread-1":
            at concurency.chapter7.Service2.s1(Service2.java:6)
            - waiting to lock <0x00000000d5f7e150> (a java.lang.Object)
            at concurency.chapter7.Service1.m1(Service1.java:16)
            - locked <0x00000000d5f806c8> (a java.lang.Object)
            at concurency.chapter7.DeadLockTest$2.run(DeadLockTest.java:21)
    "Thread-0":
            at concurency.chapter7.Service1.m2(Service1.java:21)
            - waiting to lock <0x00000000d5f806c8> (a java.lang.Object)
            at concurency.chapter7.Service2.s2(Service2.java:13)
            - locked <0x00000000d5f7e150> (a java.lang.Object)
            at concurency.chapter7.DeadLockTest$1.run(DeadLockTest.java:13)
    
    Found 1 deadlock.
    

    生产者与消费者

    单个生产者 单个消费者

    package concurency.chapter8;
    
    public class ConsumerAndProducer {
    
        int index = 0;
        private final Object LOCK = new Object();
    
        volatile boolean isProduce = false;
    
        private void produce() {
            synchronized(LOCK) {
                if( isProduce ) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    // 没生产过
                    index++;
                    System.out.println("product->" + index);
                    isProduce = true;
                    LOCK.notify();
                }
            }
        }
    
        private void consume() {
            synchronized (LOCK) {
                if(isProduce) {
                    System.out.println("consume->" + index);
                    isProduce = false;
                    LOCK.notify();
                } else {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            ConsumerAndProducer cp = new ConsumerAndProducer();
    
            new Thread("producer") {
                @Override
                public void run() {
                    while(true)
                        cp.produce();
                }
            }.start();
    
            new Thread("consumer") {
                @Override
                public void run() {
                    while (true)
                        cp.consume();
                }
            }.start();
        }
    }
    

    多个生产者 多个消费者

    package concurency.chapter8;
    
    import java.util.stream.Stream;
    
    public class ConsumerAndProducerV2 {
        int index = 0;
        private final Object LOCK = new Object();
    
        volatile boolean isProduce = false;
    
        private void produce() {
            synchronized (LOCK) {
                while(isProduce) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                index++;
                System.out.println(Thread.currentThread().getName() + " " + index);
                isProduce = true;
                LOCK.notifyAll();
            }
        }
    
        private void consume() {
            synchronized (LOCK) {
                while(!isProduce) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + " " + index);
                isProduce = false;
                LOCK.notifyAll();
            }
        }
    
        public static void main(String[] args) {
            ConsumerAndProducerV2 cp = new ConsumerAndProducerV2();
            Stream.of("Producer1", "Producer2", "Producer3").forEach((name)->{
                new Thread(name) {
                    @Override
                    public void run() {
                        while (true) {
                            cp.produce();
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
            });
    
            Stream.of("Consumer1", "Consumer2", "Consumer3", "Consumer4").forEach((name)->{
                new Thread(name) {
                    @Override
                    public void run() {
                        while(true) {
                            cp.consume();
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
            });
        }
    }
    

    wait和sleep区别

    1. sleepThread的方法,而waitobject的方法
    2. sleep will not release the monitor(LOCK), but wait will release the monitor(LOCK) and add to the object monitor waiting queue.
    3. use sleep not depend on the monitor, but wait need(synchronized).
    4. sleep not need to be wakeup, but wait must need to notify.

    数据采集多线程案例

    package concurency.chapter8;
    
    import java.util.*;
    
    /**
     * @author draymonder
     * @Date 2019/02/14
     */
    public class DataCapture {
        private static final Object LOCK = new Object();
    
        private static final int MAX = 5;
    
        private static LinkedList<Controller> list = new LinkedList<>();
    
        public static void main(String[] args) {
            ArrayList<Thread> threads = new ArrayList<>();
            // 开辟10个线程, 每个线程采集数据
            Arrays.asList("Mac1", "Mac2", "Mac3", "Mac4", "Mac5", "Mac6", "Mac7", "Mac8", "Mac9", "Mac10").stream()
                    .map(DataCapture::createDataCaptureThread).forEach(dataCaptureThread->{
                    dataCaptureThread.start();
                    // 放入threads List中
                    threads.add(dataCaptureThread);
            });
            // main线程等这10个线程 执行完再结束
            threads.forEach((thread)->{
                try {
                    thread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            Optional.of("the data capture have finished").ifPresent(System.out::println);
        }
    
        private static Thread createDataCaptureThread(String name) {
            return new Thread(()->{
                Optional.of(Thread.currentThread().getName() + " is begin").ifPresent(System.out::println);
                // 如果大于等于5个线程,后面的线程就等待
                synchronized (LOCK) {
                    while(list.size() >= MAX) {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    list.add(new Controller());
                }
                Optional.of(Thread.currentThread().getName() + " is running").ifPresent(System.out::println);
                try {
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行完毕
                synchronized (LOCK) {
                    Optional.of(Thread.currentThread().getName() + " end").ifPresent(System.out::println);
                    // 执行完  删除一个
                    list.removeFirst();
                    LOCK.notifyAll();
                }
            },name);
        }
        static class Controller{}
    }
    

    执行结果

    Mac1 is begin
    Mac1 is running
    Mac2 is begin
    Mac2 is running
    Mac3 is begin
    Mac3 is running
    Mac4 is begin
    Mac4 is running
    Mac5 is begin
    Mac5 is running
    Mac6 is begin
    Mac7 is begin
    Mac8 is begin
    Mac9 is begin
    Mac10 is begin
    Mac1 end
    Mac10 is running
    Mac2 end
    Mac6 is running
    Mac3 end
    Mac9 is running
    Mac4 end
    Mac7 is running
    Mac5 end
    Mac8 is running
    Mac10 end
    Mac9 end
    Mac7 end
    Mac6 end
    Mac8 end
    the data capture have finished
    
  • 相关阅读:
    文件上传之断点续传方案
    WEB项目(B/S系统)打包安装(总结篇)
    FLEX4.0开发流媒体视频播放器(总结篇)
    mysql 从库出现system lock延迟
    mysql与oracle 不同
    操作系统运维查询命令
    centos ifconfig 命令找不到
    bit 与 byte的区别
    mysql 登录socket与TCP
    xhost +
  • 原文地址:https://www.cnblogs.com/Draymonder/p/10380791.html
Copyright © 2020-2023  润新知