public class SimpleDateFormatTest01 {
private static final int EXECUTE_COUNT = 1000;
private static final int THREAD_COUNT = 20;
// private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
// private static Lock lock = new ReentrantLock();
// private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
// @Override
// protected DateFormat initialValue(){
// return new SimpleDateFormat("yyyy-MM-dd");
// }
// };
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
try {
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}
解决线程安全问题:
1.局部变量法:
public class SimpleDateFormatTest01 {
private static final int EXECUTE_COUNT = 1000;
private static final int THREAD_COUNT = 20;
// private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
// private static Lock lock = new ReentrantLock();
// private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
// @Override
// protected DateFormat initialValue(){
// return new SimpleDateFormat("yyyy-MM-dd");
// }
// };
//private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}
2.Synchronized锁方式:
public class SimpleDateFormatTest01 {
private static final int EXECUTE_COUNT = 1000;
private static final int THREAD_COUNT = 20;
// private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
// private static Lock lock = new ReentrantLock();
// private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
// @Override
// protected DateFormat initialValue(){
// return new SimpleDateFormat("yyyy-MM-dd");
// }
// };
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
try {
synchronized (simpleDateFormat) {
simpleDateFormat.parse("2020-01-01");
}
} catch (ParseException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}
3.Lock锁方式:
public class SimpleDateFormatTest01 {
private static final int EXECUTE_COUNT = 1000;
private static final int THREAD_COUNT = 20;
// private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
// private static Lock lock = new ReentrantLock();
// private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
// @Override
// protected DateFormat initialValue(){
// return new SimpleDateFormat("yyyy-MM-dd");
// }
// };
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
try {
lock.lock();
simpleDateFormat.parse("2020-01-01");
} catch (ParseException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
}finally {
lock.unlock();
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}
4.ThreadLocal方式:
public class SimpleDateFormatTest01 {
private static final int EXECUTE_COUNT = 1000;
private static final int THREAD_COUNT = 20;
// private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
// private static Lock lock = new ReentrantLock();
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue(){
return new SimpleDateFormat("yyyy-MM-dd");
}
};
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < EXECUTE_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
try {
threadLocal.get().parse("2020-01-01");
} catch (ParseException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("线程:" + Thread.currentThread().getName() + " 格式化日期失 败");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}
5.DateTimeFormatter方式:
DateTimeFormatter是Java8提供的新的日期时间API的类,DateTimeFormatter类是线程安全的,可以再高并发场景下直接使用。
public class DateTimeFormatterTest {
// 执行总次数
private static final int EXECUTE_COUNT = 1000;
// 同时运行的线程数量
private static final int THREAD_COUNT = 20;
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static void main(String[] args) throws Exception{
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0; i < EXECUTE_COUNT; i++){
executorService.execute(()->{
try{
semaphore.acquire();
try{
LocalDate.parse("2020-01-01",formatter);
}catch (Exception e){
System.out.println("线程:"+Thread.currentThread().getName()+"日期转换失败");
e.printStackTrace();
System.exit(1);
}
semaphore.release();
}catch (InterruptedException e){
System.out.println("信号量发生错误");
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("所有线程格式化日期成功");
}
}