Skip to content

warehouse-dev-008-test-myRLock #158

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
19 changes: 18 additions & 1 deletion springWarehouse/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,24 @@
<version>1.1.1</version>
</dependency>

</dependencies>
<!-- my custom Redis Lock -->
<!-- <dependency>-->
<!-- <groupId>com.yen</groupId>-->
<!-- <artifactId>myRLock</artifactId>-->
<!-- <version>1.0-SNAPSHOT</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.yen</groupId>-->
<!-- <artifactId>myrlock</artifactId>-->
<!-- <version>1.0.2-SNAPSHOT</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.yen</groupId>
<artifactId>myrlock</artifactId>
<version>1.0.3-TEST</version>
</dependency>

</dependencies>

<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.yen.springWarehouse.config;

// https://blog.csdn.net/u010986241/article/details/138205146

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class ThreadPoolConfig {

int CORE_POOL_SIZE = 5;
int MAX_POOL_SIZE = 10;
int QUEUE_CAPACITY = 20;
int KEEP_ALIVE_SECONDS = 30;
String THREAD_NAME_PREFIX = "custom-thread-x-";

@Bean(name="customThreadPool")
public ThreadPoolTaskExecutor threadPoolExecutor(){

System.out.println(">>>> ThreadPoolConfig init");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

return executor;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,5 @@ public ResponseEntity<Resource> downloadFile(String url) throws IOException {

return ResponseEntity.ok().headers(headers).body(resource);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.yen.springWarehouse.controller;

import com.yen.springWarehouse.service.AsyncTestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

// https://blog.csdn.net/u010986241/article/details/138205146

@Controller
@RequestMapping("/test_async")
@Slf4j
public class TestAsyncController {

@Autowired
private AsyncTestService asyncTestService;

@GetMapping("/run_task")
@ResponseBody
public String triggerAyncTasks(){

String result = null;

/** task 1 */
Runnable task1 = () -> System.out.println("Execute task 1 ...");
asyncTestService.executeAsyncTask(task1);

/** task 2 */
Callable<String> task2 = () -> {
Thread.sleep(2000);
return "Task 2 result";
};

Future<String> futureTask = asyncTestService.submitAsyncTask(task2);
// get async result
try{
result = futureTask.get();

}catch (InterruptedException | ExecutionException e){
e.printStackTrace();
}

return result;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.yen.springWarehouse.controller;

import com.yen.springWarehouse.bean.Product;
import com.yen.springWarehouse.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/test_lock")
@Slf4j
public class TestLockController {

@Autowired
TestService testService;

@GetMapping("/getLock")
@ResponseBody
public String getValueAndLock() throws Exception {

/** test getValue V1 */
//System.out.println(testService.getValue("some param"));
//System.out.println(testService.getValue("sleep"));

/** test getValue V2 */
//System.out.println(testService.getValue("sleep", 1));

/** test getValue V3 */
// Product product = new Product();
// product.setId(77);
//System.out.println(testService.getValue(product));

/** test getValue with multi-thread */
System.out.println(testService.getValueWithMultiThread("sleep"));

return "getValueAndLock done";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.yen.springWarehouse.service;

// https://blog.csdn.net/u010986241/article/details/138205146

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;

@Service
public class AsyncTestService {

@Autowired
@Qualifier("customThreadPool") // https://kucw.io/doc/springboot/8/ : specify bean name, to avoid classes with same parent type, but different name when DI
private ThreadPoolTaskExecutor taskExecutor;

public void executeAsyncTask(Runnable task){

/** V1 */
// System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
// taskExecutor.execute(task);

/** V2 */
/**
* (gpt)
*
* Ensure that your print statements (Thread.currentThread().getName() and
* Thread.currentThread().getId()) are placed within the
* execution context of tasks submitted to ThreadPoolTaskExecutor.
* This will accurately reflect the thread names from the
* thread pool configuration (custom-thread-x-1, etc.)
* rather than the container-managed thread names (http-nio-7777-exec-1).
* This adjustment should align your logging with the threads managed
* by your custom thread pool in Spring boot.
*
*/
taskExecutor.execute(() -> {
System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
task.run();
});
}

public Future<String> submitAsyncTask(Callable<String> task){

/** V1 */
// System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
// return taskExecutor.submit(task);


/** V2 */
return taskExecutor.submit(() -> {
System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
return task.call();
});

}

public void printThreadInfo(){
System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.yen.springWarehouse.service;

import com.yen.MyRLock.annotation.MyRLock;
import com.yen.MyRLock.annotation.MyRLockKey;
import com.yen.springWarehouse.bean.Product;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

import static com.yen.MyRLock.model.LockTimeoutStrategy.NO_OPERATION;
import static com.yen.MyRLock.model.LockType.Reentrant;
import static com.yen.MyRLock.model.ReleaseTimeoutStrategy.FAIL_FAST;

@Service
public class TestService {

//@MyRLock(name = "MyRLock-1", lockType = Reentrant, waitTime = Long.MAX_VALUE, leaseTime = 1000L, keys = {}, lockTimeoutStrategy = NO_OPERATION, customLockTimeoutStrategy = "", releaseTimeoutStrategy = FAIL_FAST, customReleaseTimeoutStrategy = "")
//@MyRLock(keys = {"#userId"})
//@MyRLock()
@MyRLock(name = "myRlock", waitTime = Long.MAX_VALUE, lockType = Reentrant)
public String getValue(String param) throws Exception {
System.out.println("param = " + param);
if ("sleep".equals(param)) { //线程休眠或者断点阻塞,达到一直占用锁的测试效果
System.out.println("--> Thread name : " + Thread.currentThread().getName() + ", id = " + Thread.currentThread().getId());
System.out.println("(getValue) sleep 50 sec ...");
Thread.sleep(1000 * 50); // 50 sec
}
return "success";
}

@MyRLock(keys = {"#userId"})
public String getValue(String userId, @MyRLockKey int id) throws Exception {
System.out.println("userId = " + userId + ", id = " + id);
System.out.println("(getValue with userId, id) sleep 5 sec ...");
Thread.sleep(1000 * 5);
return "success";
}

@MyRLock(keys = {"#user.name", "user.id"})
public String getValue(Product product) throws Exception {
System.out.println("product = " + product);
System.out.println("(getValue product) sleep 5 sec ...");
Thread.sleep(1000 * 5);
return "success";
}

// https://github.com/yennanliu/myRLock/blob/main/myRLock/src/test/java/MyRLock/MyRLockTests.java#L38
@MyRLock(name = "myRlock", waitTime = Long.MAX_VALUE, lockType = Reentrant)
public String getValueWithMultiThread(String param) throws Exception {

int THREAD_COUNT = 10; // Number of threads

System.out.println("getValueWithMultiThread start ...");

ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);

CountDownLatch latch = new CountDownLatch(THREAD_COUNT); // Countdown latch to wait for all threads to finish

IntStream.range(0, 30).forEach(i-> executorService.submit(() -> {
try {
Thread.sleep(1000 * 50); // 50 sec
//String result = this.getValue(param);
String result = "xxx";
System.err.println("---> Thread :[" + Thread.currentThread().getName() + "] get result =>" + result + " " + new Date().toString());
} catch (Exception e) {
System.out.println("thread execution error");
e.printStackTrace();
}finally{
latch.countDown(); // Count down the latch after thread completes
}
}));

// System.out.println("param = " + param);
// if ("sleep".equals(param)) {//线程休眠或者断点阻塞,达到一直占用锁的测试效果
// System.out.println("(getValue) sleep 5 sec ...");
// Thread.sleep(1000 * 5);
// }

// Wait until all threads complete
latch.await();

System.out.println("getValueWithMultiThread end ...");
return "success";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"king","age":17}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"king","age":17}
5 changes: 5 additions & 0 deletions springWarehouse/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.lazy-loading-enabled=true
# sql
sql.show=true

# redis
# https://github.com/yennanliu/myRLock/blob/main/myRLock/src/main/java/com/yen/MyRLock/config/MyRLockConfig.java
# prefix : spring.MyRLock
spring.MyRLock.address=redis://127.0.0.1:6379
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.yen.springWarehouse.util;

import org.junit.jupiter.api.Test;

import com.yen.MyRLock.dev.Util;

import com.yen.MyRLock.core.BusinessKeyProvider;

public class MyRLock {
@Test
public void test1(){

Util util = new Util();
System.out.println(util.add(1, 2));
System.out.println(util.substract(1, 2));
System.out.println(util.product(1, 2));
System.out.println(util.division(1, 2));
System.out.println(util.square(10));
System.out.println(util.sin(10));

BusinessKeyProvider businessKeyProvider = new BusinessKeyProvider();
System.out.println(">>> businessKeyProvider = " + businessKeyProvider);
}

}
Loading