Ace ByteDance Java Interview: Concurrency, Thread Pools, Redis & MySQL Deep Dive
This article walks through essential ByteDance Java interview topics, covering thread safety fundamentals, thread‑pool configuration, Redis performance tricks, Zset and skip‑list internals, memory‑policy handling, cache‑consistency patterns, and MySQL transaction ACID properties, providing code examples and best‑practice recommendations.
ByteDance (Autumn Recruitment First Round)
1. What is thread safety and how to guarantee it?
Thread safety means that when multiple threads access the same code or data simultaneously, the program still behaves correctly and data remains consistent.
Common thread‑safety problems include:
Data race (e.g., count++ is non‑atomic).
Read‑write inconsistency.
Visibility issues (updates not visible to other threads).
Instruction reordering.
Typical solutions:
Use synchronized to lock methods or blocks.
Use ReentrantLock for explicit locking.
Leverage atomic classes like AtomicInteger from java.util.concurrent.atomic.
Use concurrent collections such as ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue.
Mark shared variables as volatile to ensure visibility.
2. How to use a thread pool and what are its parameters?
The core purpose of a thread pool is to reuse threads, reduce the overhead of creating/destroying threads, and control concurrency.
In Java, you typically create a pool via ThreadPoolExecutor or the factory methods in Executors (e.g., newFixedThreadPool, newCachedThreadPool).
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> {
System.out.println(Thread.currentThread().getName() + " executing task");
});
pool.shutdown();The constructor parameters are:
corePoolSize : Minimum number of threads kept alive.
maximumPoolSize : Upper limit of threads; excess tasks are queued or rejected.
keepAliveTime : Time idle threads above the core size are kept before termination.
TimeUnit : Unit for keepAliveTime.
workQueue : Queue for pending tasks (e.g., LinkedBlockingQueue, ArrayBlockingQueue).
threadFactory : Custom thread creation (naming, daemon status).
handler : Rejection policy when the queue is full.
3. What are the rejection policies of a thread pool?
CallerRunsPolicy : The calling thread runs the rejected task.
AbortPolicy : Throws a RejectedExecutionException.
DiscardPolicy : Silently discards the task.
DiscardOldestPolicy : Discards the oldest queued task then retries.
Custom policies can be implemented via RejectedExecutionHandler.
4. Why is Redis fast?
Benchmark results show single‑thread Redis can achieve 100 k operations per second.
Most operations run entirely in memory with efficient data structures, making CPU not the bottleneck.
Single‑threaded design eliminates lock contention and context‑switch overhead.
Uses I/O multiplexing (select/epoll) to handle many client sockets with one thread.
5. How is Zset implemented internally?
Zset uses either a compressed list (ziplist) or a skip‑list:
If the number of elements < 128 and each element < 64 bytes, a ziplist is used.
Otherwise, a skip‑list is employed.
In Redis 7.0 the ziplist is replaced by the listpack structure.
6. What is the principle of a skip‑list?
A skip‑list is a multi‑level ordered linked list that reduces search complexity from O(N) to O(log N).
Example diagram (level 3 skip‑list) omitted for brevity.
Node structure (simplified):
typedef struct zskiplistNode {
sds ele; // element value
double score; // weight
struct zskiplistNode *backward;
struct zskiplistLevel {
struct zskiplistNode *forward;
unsigned long span;
} level[];
} zskiplistNode;Each node holds an array of zskiplistLevel structures, providing forward pointers and span for each level.
7. What happens when Redis memory is full?
Redis uses the maxmemory setting to limit memory usage. If not set, Redis consumes all available memory until the OS kills the process.
When the limit is reached, Redis applies an eviction policy defined by maxmemory-policy:
Policy
Description
noeviction
Writes are rejected; reads still work (default).
allkeys-lru
Evicts least‑recently‑used keys among all keys.
volatile-lru
Evicts LRU keys that have an expiration set.
allkeys-random
Randomly evicts any key.
volatile-random
Randomly evicts an expiring key.
volatile-ttl
Evicts keys with the shortest TTL first.
allkeys-lfu
Evicts least‑frequently‑used keys.
volatile-lfu
Evicts least‑frequently‑used expiring keys.
8. How to handle a failed Redis node?
In a single‑instance deployment, you must restart the process or restore from RDB/AOF.
In production, use high‑availability setups:
Master‑Slave : Promote a slave to master if the master fails.
Redis Sentinel : Monitors nodes and performs automatic failover.
Redis Cluster : Multiple masters with replicas; failed masters are promoted, and slots may enter a fail state requiring manual intervention.
9. How to keep MySQL and Redis data consistent?
Typical pattern: read‑through cache (load from DB on miss) and write‑through (update DB then delete cache).
Because cache sacrifices strong consistency (CAP‑AP), eventual consistency is achieved via:
Retrying cache deletions using a message queue.
Subscribing to MySQL binlog (e.g., Canal) and deleting cache based on change events.
10. Deleting cache after DB write can cause cache stampede. Solutions?
Two common approaches:
SingleFlight / Distributed mutex : Only one request fetches from DB and rebuilds the cache; others wait or fallback.
Logical expiration + background refresh : Store {data, logicalExpireAt} in cache; after expiration, serve stale data while a single request refreshes the cache asynchronously.
11. Transaction ACID properties and how InnoDB guarantees them
Atomicity : Guaranteed by undo logs for rollback.
Consistency : Ensured by combining atomicity, isolation, and durability.
Isolation : Implemented via MVCC or locking mechanisms.
Durability : Achieved with redo logs.
12. Difference of MVCC under RC and RR isolation levels
Read Committed (RC) creates a new read view before each statement, allowing non‑repeatable reads. Repeatable Read (RR) creates a single read view at transaction start, guaranteeing consistent results for the same rows throughout the transaction.
13. Hand‑written longest common subsequence (LCS) problem
The LCS problem asks for the longest subsequence common to two sequences.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
