Interview Experience and Technical Guide: HTTP Versions, Java Network Programming, OS I/O, Database Concurrency, Bloom Filter, Reflection, Annotations, and Synchronization

The article shares a graduate's interview experience and provides a comprehensive technical guide covering HTTP/1.x vs HTTP/2 differences, Java socket and HTTP server code, OS I/O buffering vs direct I/O, database concurrency control, Bloom filter principles, Java reflection, annotation usage, and synchronized locking semantics.

IT Services Circle
IT Services Circle
IT Services Circle
Interview Experience and Technical Guide: HTTP Versions, Java Network Programming, OS I/O, Database Concurrency, Bloom Filter, Reflection, Annotations, and Synchronization

This piece begins with a graduate's interview story, highlighting the importance of solid coding skills and project experience for internet development positions.

Network

Differences between HTTP/1.0, HTTP/1.1, and HTTP/2

HTTP/1.0 uses short connections by default, supports only one virtual host per IP, and has simple client‑side caching. HTTP/1.1 introduces persistent connections, Host header for virtual hosting, richer caching, and additional request methods (OPTIONS, PUT, DELETE). HTTP/2 improves performance with header compression (HPACK), binary framing, multiplexed streams to eliminate head‑of‑line blocking, and server push.

Java Network Programming – Socket Example

A simple TCP client‑server implementation demonstrates how to create a ServerSocket, accept connections, and handle client messages in separate threads.

import java.io.*;
import java.net.*;

public class SimpleServer {
    public static void main(String[] args) {
        int port = 12345; // server port
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server started, waiting for connections...");
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket.getInetAddress());
                new Thread(new ClientHandler(clientSocket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ClientHandler implements Runnable {
    private Socket clientSocket;
    public ClientHandler(Socket socket) { this.clientSocket = socket; }
    @Override
    public void run() {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                System.out.println("Received: " + inputLine);
                out.println("Echo: " + inputLine);
            }
        } catch (IOException e) { e.printStackTrace(); }
        finally { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } }
    }
}

The corresponding client code creates a Socket, reads user input, sends it to the server, and prints the server's response.

import java.io.*;
import java.net.*;

public class SimpleClient {
    public static void main(String[] args) {
        String serverAddress = "localhost";
        int port = 12345;
        try (Socket socket = new Socket(serverAddress, port);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
            String userInput;
            System.out.println("Enter messages (Ctrl+C to quit):");
            while ((userInput = stdIn.readLine()) != null) {
                out.println(userInput);
                System.out.println("Server reply: " + in.readLine());
            }
        } catch (IOException e) { e.printStackTrace(); }
    }
}

Implementing a Simple HTTP Server over TCP

Using ServerSocket, the example reads a GET request line, extracts the path, and returns a minimal HTML page with proper HTTP/1.1 response headers.

import java.io.*;
import java.net.*;

public class SimpleHttpServer {
    public static void main(String[] args) {
        int port = 8080;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("HTTP server running on port " + port);
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected: " + clientSocket.getInetAddress());
                new Thread(() -> handleRequest(clientSocket)).start();
            }
        } catch (IOException e) { e.printStackTrace(); }
    }
    private static void handleRequest(Socket clientSocket) {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
            String requestLine = in.readLine();
            if (requestLine != null && requestLine.startsWith("GET")) {
                String[] parts = requestLine.split(" ");
                String path = parts[1];
                String body = "<html><body><h1>Hello, HTTP!</h1><p>You requested: " + path + "</p></body></html>";
                out.println("HTTP/1.1 200 OK");
                out.println("Content-Type: text/html; charset=UTF-8");
                out.println("Content-Length: " + body.length());
                out.println();
                out.println(body);
            }
        } catch (IOException e) { e.printStackTrace(); }
        finally { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } }
    }
}

Operating System

I/O and Buffered I/O

Buffered I/O relies on the standard library’s cache, reducing system‑call overhead, while unbuffered I/O directly invokes system calls. Direct I/O bypasses kernel page cache, reading/writing straight to disk; non‑direct I/O uses the kernel cache and flushes it under conditions such as explicit sync, cache pressure, or timeout.

Database

Concurrent Transaction Handling

Pessimistic locking acquires row locks during reads (e.g., SELECT FOR UPDATE), whereas optimistic locking uses a version field to detect conflicts before committing updates.

Slow Query Optimization

Techniques include analyzing execution plans with EXPLAIN, creating appropriate indexes (single‑column or composite following the left‑most rule), avoiding full‑table scans, limiting SELECT *, using covering indexes, and employing caching layers like Redis.

Bloom Filter Principle

A Bloom filter consists of a bit array initialized to zero and multiple hash functions. Insertion sets bits at positions derived from the hashes; lookup checks those bits. False positives occur when different items map to the same bit pattern, but false negatives never happen.

Java Fundamentals

Reflection Example

The code shows how to obtain a Class object, retrieve a constructor, instantiate an object, and invoke a method via reflection.

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

class SampleClass {
    private String message;
    public SampleClass(String message) { this.message = message; }
    public void displayMessage() { System.out.println("Message: " + message); }
}

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("SampleClass");
            Constructor<?> ctor = clazz.getConstructor(String.class);
            Object instance = ctor.newInstance("Hello, Reflection!");
            Method method = clazz.getMethod("displayMessage");
            method.invoke(instance);
        } catch (Exception e) { e.printStackTrace(); }
    }
}

Annotation Usage

A custom annotation @MyAnnotation is defined with @Target(ElementType.TYPE) and @Retention(RetentionPolicy.RUNTIME), applied to a class, and read via reflection.

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { String value() default "default value"; }

@MyAnnotation(value = "Hello, Annotation!")
public class Example {}

public class AnnotationProcessor {
    public static void main(String[] args) {
        Class<Example> cls = Example.class;
        if (cls.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation ann = cls.getAnnotation(MyAnnotation.class);
            System.out.println("Value: " + ann.value());
        }
    }
}

Java Concurrency

synchronized Locks

Instance‑level synchronized locks the object ( this), while static‑level synchronized locks the Class object. Therefore, instance methods and static methods do not block each other, but two static synchronized methods or two instance synchronized methods on the same object are mutually exclusive.

public class MyClass {
    public synchronized void instanceMethod() { /* ... */ }
    public static synchronized void staticMethod() { /* ... */ }
}

Various scenarios are described to illustrate when mutual exclusion occurs and when concurrent execution is possible.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javadatabaseconcurrencyHTTPbloom-filterNetwork programming
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.