1. 多线程交替打印ABC
1.1 基于Synchronized实现
每个线程都抢占同一把锁,根据公有的变量判断是否能打印,否则阻塞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class PrintABC { private static final int MAX_PRINT_COUNT = 10; private static int state = 0;
public static void main(String[] args) { Object lock = new Object();
Thread threadA = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { synchronized (lock) { while (state % 3 != 0) { try { lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } System.out.print("A"); state++; lock.notifyAll(); } } });
Thread threadB = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { synchronized (lock) { while (state % 3 != 1) { try { lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } System.out.print("B"); state++; lock.notifyAll(); } } });
Thread threadC = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { synchronized (lock) { while (state % 3 != 2) { try { lock.wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } System.out.print("C"); state++; lock.notifyAll(); } } });
threadA.start(); threadB.start(); threadC.start(); } }
|
1.2
基于ReentrantLock和Condition实现
一个线程绑定同一个ReentrantLock
的不同Condition
,顺序唤醒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
public class PrintABCWithLock { private static final int MAX_PRINT_COUNT = 10; private static int state = 0;
public static void main(String[] args) { Lock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition();
Thread threadA = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { lock.lock(); try { while (state % 3 != 0) { conditionA.await(); } System.out.print("A"); state++; conditionB.signal(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); } } });
Thread threadB = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { lock.lock(); try { while (state % 3 != 1) { conditionB.await(); } System.out.print("B"); state++; conditionC.signal(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); } } });
Thread threadC = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { lock.lock(); try { while (state % 3 != 2) { conditionC.await(); } System.out.print("C"); state++; conditionA.signal(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { lock.unlock(); } } });
threadA.start(); threadB.start(); threadC.start(); } }
|
1.3 基于Semaphore实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import java.util.concurrent.Semaphore;
public class PrintABCWithSemaphore { private static final int MAX_PRINT_COUNT = 10;
public static void main(String[] args) { Semaphore semaphoreA = new Semaphore(1); Semaphore semaphoreB = new Semaphore(0); Semaphore semaphoreC = new Semaphore(0);
Thread threadA = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { try { semaphoreA.acquire(); System.out.print("A"); semaphoreB.release(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } });
Thread threadB = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { try { semaphoreB.acquire(); System.out.print("B"); semaphoreC.release(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } });
Thread threadC = new Thread(() -> { for (int i = 0; i < MAX_PRINT_COUNT; i++) { try { semaphoreC.acquire(); System.out.print("C"); semaphoreA.release(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } });
threadA.start(); threadB.start(); threadC.start(); } }
|
2. 单例模式
2.1 懒汉
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Singleton { private static Singleton instance; private Singleton() {}
public static Singleton getInstance() {
if(instance == null) { instance = new Singleton(); } return instance; } }
|
2.2 饿汉
1 2 3 4 5 6 7 8 9
| public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {}
public static Singleton getInstance() { return instance; } }
|
2.1 双检锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Singleton { private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
|
3.
一个线程等待三个并发线程全部执行完再执行
可以使用 CountDownLatch
来实现 3
个线程并发执行,另一个线程等待这三个线程全部执行完再执行的需求。以下是具体的实现步骤:
- 创建一个
CountDownLatch
对象,并将计数器初始化为
3,因为有 3 个线程需要等待。
- 创建 3 个并发执行的线程,在每个线程的任务结束时调用
countDown
方法将计数器减 1。
- 创建第 4 个线程,使用
await
方法等待计数器为
0,即等待其他 3 个线程完成任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample { public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) { final int threadNumber = i + 1; new Thread(() -> { try { System.out.println("Thread " + threadNumber + " is working."); Thread.sleep((long) (Math.random() * 1000)); System.out.println("Thread " + threadNumber + " has finished."); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); } }).start(); }
new Thread(() -> { try { System.out.println("Waiting for other threads to finish."); latch.await(); System.out.println("All threads have finished, this thread starts to work."); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } }
|
4. 生产者消费者模型
这里假定生产者10s生产一个,消费者4s消费一个
生产者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable { public BlockingQueue<Integer> queue;
public Producer(BlockingQueue queue) { this.queue = queue; }
@Override public void run() { while (true) { try { Thread.sleep(10000); queue.add(1); System.out.println("生产者生产一个产品"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
|
消费者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable { public BlockingQueue<Integer> queue;
public Consumer(BlockingQueue queue) { this.queue = queue; }
@Override public void run() { while (true) { try { Thread.sleep(4000); queue.take(); System.out.println("消费者消费一个产品"); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }
|
执行类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue;
public class Main { public static void main(String[] args) { BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(100); Producer producer = new Producer(queue); Consumer consumer = new Consumer(queue); Thread threadA = new Thread(producer); Thread threadB = new Thread(consumer); threadA.start(); threadB.start(); } }
|
5. JDK动态代理
这里以HelloService为例进行示意
目标类实现的接口HelloService
,这个接口目标类和代理类都需要实现
1 2 3
| public interface HelloService { String sayHello(); }
|
目标类HelloServiceImpl
1 2 3 4 5
| public class HelloServiceImpl implements HelloService { public String sayHello() { return "Hello, JDK Proxy!"; } }
|
代理类MyInvocationHandler
,需要实现InvocationHandler
接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler { private Object target;
public MyInvocationHandler(Object target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before invoking " + method.getName()); Object result = method.invoke(target, args); System.out.println("After invoking " + method.getName()); return result; } }
|
测试类Test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;
public class Test { public static void main(String[] args) { HelloService target = new HelloServiceImpl(); InvocationHandler handler = new MyInvocationHandler(target); HelloService proxy = (HelloService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); String result = proxy.sayHello(); System.out.println(result); } }
|