@Slf4j public class SingletonPerformanceTest { static long timeout = 20; // 超时时间,单位为秒 static int testIterations = 10_000_000; // 测试次数 static int threadCount = 1000; // 并发线程数 static Map<String, HashMap<String, Long>> result = new HashMap<>();
PC Register(程序计数器) 程序计数器是程序控制流的指示器,循环,跳转,异常处理,线程的恢复等工作都需要依赖程序计数器去完成。程序计数器是线程私有的,它的生命周期是和线程保持一致的,我们知道,N 个核数的 CPU 在同一时刻,最多有 N个线程同时运行,在我们真实的使用过程中可能会创建很多线程,JVM 的多线程其实是通过线程轮流切换,分配处理器执行时间来实现的。既然涉及的线程切换,所以每条线程必须有一个独立的程序计数器。
public class Test01_01 extends Thread{ @Override public void run() { for (int i = 0; i < 5; i++) { logger.info("thread sout:"+i); } } }
运行方式如下
language-java
1 2
Thread t = new Test01_01(); t.start();
其二
实现Runnable接口,重写run方法,这种方式避免了无法继承别的类的缺陷。
language-java
1 2 3 4 5 6 7 8 9 10 11 12
public class Test02_01 implements Runnable{ @Override public void run() { Thread cut = Thread.currentThread(); for (int i = 0; i < 5; i++) { System.out.println("thread ["+cut.getName()+"]"+i); } } }
运行方式如下
language-java
1 2
Runnable target = new Test02_01(); new Thread(target).start();
或者使用lambda表达式
language-java
1 2 3 4 5 6 7 8
new Thread(()->{ Thread cut = Thread.currentThread(); for (int i = 0; i < 5; i++) { System.out.println("thread ["+cut.getName()+"]"+i); } }).start();
其三
实现Callable接口,重写call方法,这种方式可以取得线程的返回值。
language-java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
private static class Test04_01 implements Callable<Long>{ @Override public Long call() throws Exception { Thread cut = Thread.currentThread(); System.out.println("当前线程:"+cut.getName()); long res = 0; for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { res += j; } } return res; } };
运行方式如下
language-java
1 2 3 4 5
Callable<Long> call = new Test04_01(); FutureTask<Long> task = new FutureTask<>(call); new Thread(task).start(); Long l = task.get(); System.out.println(l);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 5, 8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
public class PostLock01 { private static class MyRunnable01 implements Runnable{ private int number; @Override public void run() { for (int i = 0; i < 1000; i++) { synchronized (this){ ++number; } } } }; private static class MyRunnable02 implements Runnable{ // private int number; private AtomicInteger number = new AtomicInteger(); @Override public void run() { for (int i = 0; i < 1000; i++) { number.incrementAndGet(); } } };
@Slf4j @Configuration public class PayNotifyConfig{
//交换机 public static final String PAYNOTIFY_EXCHANGE_FANOUT = "paynotify_exchange_fanout"; //支付通知队列 public static final String PAYNOTIFY_QUEUE = "paynotify_queue"; //支付结果通知消息类型 public static final String MESSAGE_TYPE = "payresult_notify";
//声明交换机,且持久化 @Bean(PAYNOTIFY_EXCHANGE_FANOUT) public FanoutExchange paynotify_exchange_fanout() { // 三个参数:交换机名称、是否持久化、当没有queue与其绑定时是否自动删除 return new FanoutExchange(PAYNOTIFY_EXCHANGE_FANOUT, true, false); } //支付通知队列,且持久化 @Bean(PAYNOTIFY_QUEUE) public Queue paynotify_queue() { return QueueBuilder.durable(PAYNOTIFY_QUEUE).build(); }
在 Spring Boot 开发中,我们时常遇到需要在一个类的内部调用自己的其他方法,并且这些方法可能需要事务支持。这种场景通常发生在业务逻辑较为复杂的服务类中,其中一些操作需要确保数据的一致性和完整性。本文将以 MediaFileServiceImpl 类为例,探讨如何在 Spring Boot 中有效地使用当前类的代理类来处理内部事务。
一、场景描述
考虑一个典型的例子:在 MediaFileServiceImpl 服务类中,upload 方法需要调用 upload2Mysql 方法。这里,upload2Mysql 方法是事务性的,意味着它涉及到数据库操作,这些操作需要在一个事务中被处理。如果直接在 upload 方法中调用 upload2Mysql,由于 Spring 的代理方式,事务管理可能不会被正确应用,因为实际上是在同一个实例内部进行方法调用,绕过了 Spring 的代理。