Java 多线程编程

线程的创建方式、生命周期、同步与线程池。

Intermediate
Key Points实现 Runnable 优于继承 Thread;共享可变状态必须同步;生产代码用线程池而不是手动 new Thread。

创建一个线程

Two ways: extend Thread and override run(), or implement Runnable and hand it to a Thread. The latter is more flexible and works with pools and lambdas.

Java
public class CreateThread {
    static class ByExtend extends Thread {
        @Override
        public void run() {
            System.out.println("extend Thread");
        }
    }

    public static void main(String[] args) throws Exception {
        Thread t1 = new ByExtend();
        t1.start();
        t1.join();

        Thread t2 = new Thread(() -> System.out.println("implement Runnable"));
        t2.start();
        t2.join();

        System.out.println(t1.getState());
    }
}
Output
extend Thread
implement Runnable
TERMINATED
Calling run() is an ordinary method call on the current thread; only start() spawns a new one. This is the classic beginner mistake.

线程的生命周期

Six states: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED. sleep gives TIMED_WAITING, waiting for a lock gives BLOCKED, and join gives WAITING.

Java
public class Lifecycle {
    public static void main(String[] args) throws Exception {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        System.out.println(t.getState());
        t.start();
        System.out.println(t.getState());
        t.join();
        System.out.println(t.getState());
    }
}
Output
NEW
RUNNABLE
TERMINATED

线程同步

Concurrent updates get lost because count++ is not atomic. Guard with synchronized, or switch to atomics such as AtomicInteger or LongAdder.

Java
import java.util.concurrent.atomic.AtomicInteger;

public class SyncDemo {
    static int unsafe = 0;
    static int safe = 0;
    static AtomicInteger atomic = new AtomicInteger();

    static synchronized void inc() {
        safe++;
    }

    public static void main(String[] args) throws Exception {
        Thread[] ts = new Thread[10];
        for (int i = 0; i < ts.length; i++) {
            ts[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    unsafe++;
                    inc();
                    atomic.incrementAndGet();
                }
            });
            ts[i].start();
        }
        for (Thread t : ts) {
            t.join();
        }

        System.out.println(safe);
        System.out.println(atomic.get());
        System.out.println(unsafe <= 10000);
    }
}
Output
10000
10000
true

线程池

Executors.newFixedThreadPool(n) creates a fixed pool, submit hands it work and shutdown stops accepting new tasks. In production prefer ThreadPoolExecutor with an explicit queue and rejection policy.

Java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class PoolDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(2);

        Future<Integer> f = pool.submit(() -> 1 + 2);
        System.out.println(f.get());

        pool.shutdown();
        System.out.println(pool.isShutdown());
    }
}
Output
3
true

Friends & Partners