🚀 Day 12 – Runnable vs Callable (and why Future matters) While working with threads, I explored the difference between "Runnable" and "Callable". 👉 We often use "Runnable": Runnable task = () -> { System.out.println("Running task"); }; ✔ Doesn’t return any result ✔ Cannot throw checked exceptions --- 👉 Now "Callable": Callable<Integer> task = () -> { return 10; }; ✔ Returns a result ✔ Can throw checked exceptions --- 💡 So where does "Future" come in? Future<Integer> result = executor.submit(task); Integer value = result.get(); 👉 "Future" acts as a placeholder for the result of an asynchronous computation --- 💡 Key takeaway: - Use "Runnable" → when no result is needed - Use "Callable" → when you need result or exception handling This becomes very useful when working with ExecutorService in real applications. #Java #BackendDevelopment #Multithreading #Concurrency #LearningInPublic
Runnable vs Callable in Java: When to Use Each
More Relevant Posts
-
I used to run parallel tasks using ExecutorService… But something always felt incomplete 🤔 Yes, tasks were running concurrently… But how do you know when ALL of them are done? That’s when I discovered the combo: 👉 ExecutorService + CountDownLatch And honestly, this is where multithreading started to make real sense. ⸻ 💡 The idea is simple: • ExecutorService → runs tasks in parallel ⚡ • CountDownLatch → makes sure you wait for all of them ⏳ ⸻ 🔥 Real flow: 1. Create a thread pool using ExecutorService 2. Initialize CountDownLatch with count = number of tasks 3. Submit tasks 4. Each task calls countDown() when done 5. Main thread calls await() 👉 Boom — main thread continues only when everything is finished ✅ ⸻ 🧠 Why this matters: ✔ Clean coordination between threads ✔ No messy shared variables ✔ Perfect for parallel API calls, batch processing, etc. ⸻ Before this, I was just “running threads” Now I’m actually controlling concurrency That’s a big difference. ⸻ If you’re learning backend or system design, this combo is 🔥 Simple tools… powerful impact. Have you used this pattern in real projects? 👇 #Java #Multithreading #ExecutorService #CountDownLatch #BackendDevelopment #LearningInPublic
To view or add a comment, sign in
-
-
I used to think managing multiple threads was just about starting them… until I learned about CountDownLatch 👀 At first, I had a simple problem: 👉 “Run multiple tasks in parallel… but wait until ALL of them finish” My old approach? ❌ Manual tracking ❌ Shared variables ❌ Messy and error-prone Then I discovered CountDownLatch — and everything clicked. ⸻ 💡 What it does: It lets one thread wait until other threads complete their work. 👉 You set a count 👉 Each task reduces it (countDown()) 👉 Main thread waits (await()) When count = 0 → everything proceeds ✅ ⸻ 🔹 Real-world use cases: ✔ Waiting for multiple APIs to respond ✔ Running parallel tasks before processing results ✔ Ensuring services are ready before starting execution ⸻ 🔥 Simple flow: Start 3 tasks → count = 3 Task 1 done → count = 2 Task 2 done → count = 1 Task 3 done → count = 0 👉 Main thread continues ⸻ This changed how I think about concurrency: 👉 It’s not just about running things in parallel 👉 It’s about coordinating them correctly ⸻ Small utility… but super powerful in multithreaded systems. Have you used CountDownLatch in your projects? 👇 #Java #Multithreading #Concurrency #BackendDevelopment #LearningInPublic
To view or add a comment, sign in
-
-
How ConcurrentHashMap Works Internally 1. Core Idea • No global lock • Uses CAS + fine-grained (bucket-level) locking • Allows multiple reads and concurrent writes 2. Structure • Array + buckets • Buckets → Linked List → Tree (if collisions grow) 3. Reads (get) • Completely lock-free • Uses volatile for visibility 👉 Very fast under concurrency 4. Writes (put) • Empty bucket → CAS (no lock) • Non-empty → lock only that bucket 👉 Minimal contention 5. Resizing • Not single-threaded • Multiple threads help rehash 👉 No major pause 6. Why It Scales • Lock-free reads • Localized locking • CAS for fast updates ConcurrentHashMap works because it avoids global locks and minimizes contention 👉 Balance of: • CAS • Bucket-level locks • Parallel resize #SystemDesign #Java #Concurrency #ConcurrentHashMap #BackendEngineering #Scalability #Performance
To view or add a comment, sign in
-
-
Most backend bugs in production aren't caused by bad code. They arise from assumptions that were never questioned during development. Common assumptions include: - "This API will always return data." - "The network will always be stable." - "No one will hit this endpoint 1000 times a minute." Defensive programming isn't pessimism; it's simply experience wearing a helmet. #BackendDevelopment #SoftwareEngineering #Java #LessonsLearned
To view or add a comment, sign in
-
🚨 Hot take: Most “async” Java code isn’t actually asynchronous — it’s just parallel blocking. I recently reviewed a service using CompletableFuture everywhere… ⚠️ but response time was still bad. ❓ Why? Because .get() was called almost immediately after supplyAsync(). 👉 At that point, the code not doing async — the code just adding complexity. 💡 What actually made a difference: ✅ Letting futures complete without blocking 🔗 Combining results instead of waiting on each call ⚙️ Controlling thread pools instead of relying on defaults 🚫 Async done wrong = harder debugging, unstable latency, pressure on downstream systems 🚀 Async done right = better orchestration, not just faster code 🧠 Most systems don’t have a performance problem — they have a design problem disguised as async. 💬 Curious — how often have you seen “fake async” in real projects? #Java #SystemDesign #Microservices #BackendEngineering #AsyncProgramming #TechLeadership
To view or add a comment, sign in
-
Most developers think @Autowired is just dependency injection. It's not ❌ It's Reflection + Proxies + Runtime Wiring. Which means : ⭕ Dependencies are injected at runtime (not compile time) ⭕ You might be calling a proxy, not your actual class ⭕ Field injection hides dependencies and hurts testability ⭕ Startup time increases as your app grows The biggest surprise : 👉 this.method() can bypass Spring logic completely (broken @Transactional) Lesson : "Convenience annotations often hide real complexity." Do you still use Field Injection in production ? #SpringBoot #Java #BackendEngineering #SoftwareArchitecture
To view or add a comment, sign in
-
Day 31/50 🚀 — Reverse Vowels of a String (LeetCode 345) Today’s problem was a great reminder that sometimes the simplest approaches are the most efficient. 🔹 Used the two-pointer technique 🔹 Focused on in-place swapping 🔹 Optimized for both time (O(n)) and space (O(1)) Key takeaway: Instead of overthinking, break the problem into smaller checks—identify vowels, move pointers smartly, and swap only when needed. Clean and efficient 💡 Happy to see this solution performing well: ⚡ Runtime: 2 ms (faster than 99%+) 📦 Space: Decent optimization #Day31 #LeetCode #DSA #Java #CodingJourney #50DaysOfCode #ProblemSolving #SoftwareEngineering
To view or add a comment, sign in
-
-
🚀 Day 9/30 — LeetCode Challenge Solved a problem on LeetCode involving "mirror distance of a number" The task was to reverse the digits of a number and compute the absolute difference with the original value. ✅ Key takeaway: Simple problems still reinforce core concepts like "digit manipulation and number handling" Consistency continues. #LeetCode #Java #ProblemSolving #Consistency
To view or add a comment, sign in
-
-
#Post11 In the previous post(https://lnkd.in/dynAvNrN), we saw how to create threads in Java. Now let’s talk about a problem. If creating threads is so simple… why don’t we just create a new thread every time we need one? Let’s say we are building a backend system. For every incoming request/task, we create a new thread: new Thread(() -> { // process request }).start(); This looks simple. But this approach breaks very quickly in real systems because of below mentioned problems. Problem 1: Thread creation is expensive Creating a thread is not just creating an object. It involves: • Allocating memory (stack) • Registering with OS • Scheduling overhead Creating thousands of threads = performance degradation Problem 2: Too many threads → too much context switching We already saw this earlier(https://lnkd.in/dYG3v-vb). More threads does NOT mean more performance. Instead: • CPU spends more time switching • Less time doing actual work Problem 3: No control over thread lifecycle When you create threads manually: • No limit on number of threads • No reuse • Hard to manage failures This quickly becomes difficult to manage as the system grows. So what’s the solution? Instead of creating threads manually: we use something called the Executor Framework. In simple words consider the framework to be like: Earlier, we were manually hiring a worker (thread) for every task. With Executor, we have a team of workers (thread pool), and we just assign tasks to them. Key idea Instead of: Creating a new thread for every task We do: Submit tasks to a pool of reusable threads This is exactly what Java provides using: Executor Framework Key takeaway Manual thread creation works for learning, but does not scale in real-world systems. Thread pools help: • Control number of threads • Reduce overhead • Improve performance We no longer manage threads directly — we delegate that responsibility to the Executor Framework. In the next post, we’ll see how Executor Framework works and how to use it in Java. #Java #Multithreading #Concurrency #BackendDevelopment #SoftwareEngineering
To view or add a comment, sign in
-
Day 7/60 – Backend Development Journey (Multithreading & Synchronization) Today I worked on Java Multithreading and understood how concurrent execution works along with synchronization. What I built Task 1: Parallel Execution: Created two threads to print numbers: • Thread 1 → prints 1 to 5 • Thread 2 → prints 6 to 10 Both run simultaneously using Runnable Task 2: Shared Counter with Synchronization: • Two threads increment a shared counter • Ensured correct final value using locking mechanism Key Concepts Applied 1. Multithreading Running multiple threads in parallel to improve performance. Example 1: • Thread A → handles API requests • Thread B → processes background tasks Example 2: • Thread 1 → file download • Thread 2 → UI updates 2. Race Condition Multiple threads accessing shared data can cause incorrect results. Example 1: • Two threads incrementing the same variable → wrong count Example 2: • Bank balance updates → inconsistent values 3. Synchronization & Locking • Used ReentrantLock to ensure only one thread updates the counter at a time. 4. Thread Coordination • Used join() to wait for threads to finish before printing result. #Java #Multithreading #Concurrency #Threading #Synchronization
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development