怎么做婚介网站,物联网平台软件开发,网站建设综合实训ppt,网站logo设计标准有面试题#xff0c;有synchronized锁#xff0c;threadlocal 一、面试题小记二、加锁synchronized1. 先看代码2. synchronized 讲解2.1. 同步代码块2.2. 同步方法2.3. 锁的选择和影响2.4. 注意事项2.5 锁的操作#xff0c;手动释放锁#xff0c;显式地获取锁#xff08;属… 有面试题有synchronized锁threadlocal 一、面试题小记二、加锁synchronized1. 先看代码2. synchronized 讲解2.1. 同步代码块2.2. 同步方法2.3. 锁的选择和影响2.4. 注意事项2.5 锁的操作手动释放锁显式地获取锁属性名第一个lock代表的是 三、ThreadLocal1. 基本用法2. ThreadLocal 的关键方法3. 使用场景4. 注意事项5. 示例使用 ThreadLocal 进行数据库连接管理 四、数据库用来设置某个字段的默认值。五、 把redis的json转为对象1. 从 Redis 获取 JSON 数据2 使用 Gson 一切都是自己的笔记请勿上纲上线 一、面试题小记 java10 本地类型推断 switch表达式
二、加锁synchronized
1. 先看代码
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.HashSet;public class Example {private static final SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd);private static final SetString dates new HashSet();private static final CountDownLatch countDownLatch new CountDownLatch(10);private static final ExecutorService pool Executors.newFixedThreadPool(10);public void addDate(int i) {Calendar calendar Calendar.getInstance(); // 创建Calendar实例int finalI i; // final变量用于在lambda表达式中使用pool.execute(() - {synchronized (simpleDateFormat) { // 对simpleDateFormat加锁// 时间增加calendar.add(Calendar.DATE, finalI);// 通过simpleDateFormat把时间转换成字符串String dateString simpleDateFormat.format(calendar.getTime());// 把字符串放入Set中dates.add(dateString);}// CountDowncountDownLatch.countDown();});}public void awaitCompletion() throws InterruptedException {countDownLatch.await(); // 等待所有线程完成pool.shutdown(); // 关闭线程池}public static void main(String[] args) throws InterruptedException {Example example new Example();for (int i 0; i 10; i) {example.addDate(i); // 添加日期}example.awaitCompletion(); // 等待所有线程完成System.out.println(dates); // 输出结果}
}2. synchronized 讲解 synchronized 是 Java 中用于实现线程同步的关键字确保多个线程在执行某段代码时不会发生冲突从而保证线程安全。它有两种主要的使用方式同步代码块和同步方法。 2.1. 同步代码块 通过 synchronized 关键字修饰的代码块可以确保在同一时间只有一个线程可以执行该代码块中的代码。以下是如何使用同步代码块的示例 public class SynchronizedBlockExample {private final Object lock new Object(); // 用于锁定的对象public void doWork() {synchronized (lock) { // 对 lock 对象加锁// 临界区代码System.out.println(Thread Thread.currentThread().getName() is working.);} // 离开synchronized块时自动释放锁}
}锁定对象synchronized (lock) 表示对 lock 对象加锁。只有获取了 lock 锁的线程可以执行 synchronized 块中的代码。 自动释放当线程退出 synchronized 块包括发生异常的情况JVM 会自动释放锁。 2.2. 同步方法
synchronized 也可以用于修饰方法这样整个方法在同一时间只会被一个线程执行。同步方法可以分为实例方法和静态方法
实例同步方法锁定的是方法所在对象的实例。
public class SynchronizedMethodExample {public synchronized void instanceMethod() {// 临界区代码System.out.println(Thread Thread.currentThread().getName() is working.);}
}静态同步方法锁定的是类的 Class 对象。静态同步方法同一时间只允许一个线程访问类的所有实例的静态方法。
public class SynchronizedStaticMethodExample {public static synchronized void staticMethod() {// 临界区代码System.out.println(Thread Thread.currentThread().getName() is working.);}
}2.3. 锁的选择和影响
对象锁在同步代码块中指定的对象例如 lock 对象会作为锁对象。这种锁是对象级别的不同对象的同步代码块不会互相影响。
类锁对于静态同步方法锁的是类的 Class 对象。这意味着类的所有静态同步方法是互斥的。
锁的粒度选择锁的粒度时需要考虑性能和安全。粒度过大例如锁住整个方法或类可能导致性能下降而粒度过小则可能无法有效防止数据竞争。
2.4. 注意事项
死锁多个线程可能互相等待对方释放锁导致系统僵死。应避免复杂的锁定顺序和嵌套锁。
性能开销同步会引入性能开销因为它涉及到线程上下文的切换和锁管理。只在必要时使用同步尽量减少锁的持有时间。
不可重入虽然 synchronized 是可重入的即同一个线程可以多次获取同一个锁但在设计时仍需注意避免复杂的锁定结构。
总结 同步代码块通过 synchronized (lock) 对特定的对象进行加锁确保只有一个线程能执行代码块中的代码。 同步方法通过 synchronized 关键字修饰实例方法或静态方法确保方法在同一时间内只有一个线程能执行。
2.5 锁的操作手动释放锁显式地获取锁属性名第一个lock代表的是
lock.lock()显式地获取锁。 lock.unlock()在 finally 块中释放锁以确保即使发生异常也能释放锁。
三、ThreadLocal ThreadLocal 是 Java 中用于实现线程局部存储的类允许每个线程在访问某个变量时拥有自己的独立副本。这样每个线程都可以操作自己的副本而不会与其他线程的副本发生冲突。ThreadLocal 主要用于需要线程隔离的场景例如每个线程需要独立的配置、数据库连接、会话等。 1. 基本用法
ThreadLocal 的基本用法非常简单。可以通过 ThreadLocal 提供的 get 和 set 方法来获取和设置当前线程的值。
public class ThreadLocalExample {private static final ThreadLocalInteger threadLocalValue ThreadLocal.withInitial(() - 1);public static void main(String[] args) {Runnable task () - {// 获取当前线程的线程局部变量值Integer value threadLocalValue.get();System.out.println(Initial Value: value);// 设置当前线程的线程局部变量值threadLocalValue.set(value 1);// 再次获取当前线程的线程局部变量值System.out.println(Updated Value: threadLocalValue.get());};// 创建多个线程测试每个线程的线程局部变量是否独立Thread thread1 new Thread(task);Thread thread2 new Thread(task);thread1.start();thread2.start();}
}2. ThreadLocal 的关键方法
ThreadLocal.withInitial(Supplier? extends T supplier)创建一个 ThreadLocal 实例并设置初始值。这个方法可以指定一个 Supplier 来提供初始值。
T get()获取当前线程的 ThreadLocal 变量的值。如果当前线程没有设置过这个值则会调用 initialValue() 方法来设置初始值。
void set(T value)设置当前线程的 ThreadLocal 变量的值。
void remove()移除当前线程的 ThreadLocal 变量的值防止内存泄漏。
3. 使用场景
ThreadLocal 主要适用于以下场景
数据库连接每个线程需要一个独立的数据库连接。
用户会话每个线程需要维护独立的用户会话信息。
配置和上下文每个线程需要独立的配置或上下文信息。
4. 注意事项
内存泄漏如果 ThreadLocal 的 ThreadLocalMap 中的 ThreadLocal 引用被持有而没有被正确清理通过调用 remove() 方法可能会导致内存泄漏特别是在长期运行的应用中。由于 ThreadLocal 是线程本地的它的值只会在当前线程中有效所以如果线程池中线程长时间存在而没有被回收就可能导致内存泄漏。
适用性ThreadLocal 适用于线程独立的场景。如果不同线程之间需要共享数据考虑使用其他同步机制如 synchronized 或 Concurrent 数据结构。
性能虽然 ThreadLocal 提供了线程隔离但它也有一定的性能开销。避免在高并发场景中频繁使用 ThreadLocal特别是当线程局部变量对象较大或线程较多时。
5. 示例使用 ThreadLocal 进行数据库连接管理
public class DatabaseConnectionManager {private static final ThreadLocalConnection connectionHolder ThreadLocal.withInitial(() - {try {return DriverManager.getConnection(jdbc:yourdb, username, password);} catch (SQLException e) {throw new RuntimeException(e);}});public static Connection getConnection() {return connectionHolder.get();}public static void closeConnection() {Connection connection connectionHolder.get();if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();} finally {connectionHolder.remove(); // 清理线程局部变量}}}
}在这个示例中每个线程会有自己独立的数据库连接使用完后记得调用 remove() 方法以避免潜在的内存泄漏。
四、数据库用来设置某个字段的默认值。
ALTER TABLE in_inspect_info ALTER result SET DEFAULT 1;
五、 把redis的json转为对象
从 Redis 中获取 JSON 数据并将其转换为 Java 对象通常涉及以下几个步骤
从 Redis 获取 JSON 数据: 你可以使用 Redis 客户端库例如 Jedis 或 Lettuce从 Redis 中获取存储的 JSON 数据。 将 JSON 转换为 Java 对象: 使用 JSON 解析库如 Jackson 或 Gson将 JSON 字符串转换为 Java 对象。 以下是详细的步骤和代码示例
1. 从 Redis 获取 JSON 数据
假设你使用 Jedis 作为 Redis 客户端库首先从 Redis 中获取 JSON 数据
import redis.clients.jedis.Jedis;public class RedisExample {public static void main(String[] args) {// 创建 Jedis 实例Jedis jedis new Jedis(localhost, 6379);// 从 Redis 中获取 JSON 数据String jsonData jedis.get(yourRedisKey);// 关闭 Jedis 连接jedis.close();// 打印获取到的 JSON 数据System.out.println(jsonData);}
}将 JSON 转换为 Java 对象 使用 Jackson 或 Gson 库将 JSON 字符串转换为 Java 对象。以下是使用 Jackson 和 Gson 的示例。
使用 Jackson 添加依赖如果你使用 Maven可以在 pom.xml 中添加以下依赖
dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.14.2/version
/dependency转换 JSON
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonExample {public static void main(String[] args) {String jsonData {\term_sn\:\12345\,\devid_qi_cname\:\设备名称\,\devid_qi_time\:\2024-07-22T10:00:00Z\,\inspect_list\:[{\code\:\INS001\,\name\:\检查1\,\term_sn\:\TERM001\,\inspect_ask\:\检查要求1\,\result\:\结果1\},{\code\:\INS002\,\name\:\检查2\,\term_sn\:\TERM002\,\inspect_ask\:\检查要求2\,\result\:\结果2\}],\dq_info_file_ids\:98765,\devidqi_state\:1};ObjectMapper objectMapper new ObjectMapper();try {// 将 JSON 转换为 Java 对象MyClass myObject objectMapper.readValue(jsonData, MyClass.class);// 打印转换后的对象System.out.println(myObject);} catch (Exception e) {e.printStackTrace();}}
}class MyClass {private String term_sn;private String devid_qi_cname;private String devid_qi_time;private ListInspect inspect_list;private int dq_info_file_ids;private int devidqi_state;// Getter 和 Setter 方法Overridepublic String toString() {return MyClass{ term_sn term_sn \ , devid_qi_cname devid_qi_cname \ , devid_qi_time devid_qi_time \ , inspect_list inspect_list , dq_info_file_ids dq_info_file_ids , devidqi_state devidqi_state };}
}class Inspect {private String code;private String name;private String term_sn;private String inspect_ask;private String result;// Getter 和 Setter 方法Overridepublic String toString() {return Inspect{ code code \ , name name \ , term_sn term_sn \ , inspect_ask inspect_ask \ , result result \ };}
}2 使用 Gson
添加赖如果你使用 Maven可以在 pom.xml 中添加以下依赖
dependencygroupIdcom.google.code.gson/groupIdartifactIdgson/artifactIdversion2.10.1/version
/dependency转换 JSON
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;public class JsonExample {public static void main(String[] args) {String jsonData {\term_sn\:\12345\,\devid_qi_cname\:\设备名称\,\devid_qi_time\:\2024-07-22T10:00:00Z\,\inspect_list\:[{\code\:\INS001\,\name\:\检查1\,\term_sn\:\TERM001\,\inspect_ask\:\检查要求1\,\result\:\结果1\},{\code\:\INS002\,\name\:\检查2\,\term_sn\:\TERM002\,\inspect_ask\:\检查要求2\,\result\:\结果2\}],\dq_info_file_ids\:98765,\devidqi_state\:1};Gson gson new Gson();// 将 JSON 转换为 Java 对象MyClass myObject gson.fromJson(jsonData, MyClass.class);// 打印转换后的对象System.out.println(myObject);}
}class MyClass {private String term_sn;private String devid_qi_cname;private String devid_qi_time;private ListInspect inspect_list;private int dq_info_file_ids;private int devidqi_state;// Getter 和 Setter 方法Overridepublic String toString() {return MyClass{ term_sn term_sn \ , devid_qi_cname devid_qi_cname \ , devid_qi_time devid_qi_time \ , inspect_list inspect_list , dq_info_file_ids dq_info_file_ids , devidqi_state devidqi_state };}
}class Inspect {private String code;private String name;private String term_sn;private String inspect_ask;private String result;// Getter 和 Setter 方法Overridepublic String toString() {return Inspect{ code code \ , name name \ , term_sn term_sn \ , inspect_ask inspect_ask \ , result result \ };}
}关键点总结 选择合适的库: Jackson 和 Gson 都是流行的 JSON 解析库可以根据你的需求选择其中一个。 确保字段匹配: JSON 字段名称应与 Java 类中的字段名称匹配注意大小写和命名风格。 处理日期: 如果 JSON 中包含日期确保正确解析和格式化日期字段。