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

猜你喜欢

转载自www.cnblogs.com/Draymonder/p/10380791.html