Java 多线程编程
线程的创建方式、生命周期、同步与线程池。
创建一个线程
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.
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());
}
}extend Thread
implement Runnable
TERMINATEDrun() 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.
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());
}
}NEW
RUNNABLE
TERMINATED线程同步
Concurrent updates get lost because count++ is not atomic. Guard with synchronized, or switch to atomics such as AtomicInteger or LongAdder.
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);
}
}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.
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());
}
}3
true创建一个线程
两种方式:继承 Thread 重写 run(),或实现 Runnable 交给 Thread。后者更灵活(还能继承别的类),也便于配合线程池和 lambda。
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());
}
}extend Thread
implement Runnable
TERMINATEDrun() 只是普通方法调用,仍在当前线程执行;只有 start() 才会开新线程。这是最常见的初学者错误。线程的生命周期
状态有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 六种。sleep 进 TIMED_WAITING,等锁进 BLOCKED,join 等另一线程结束进 WAITING。
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());
}
}NEW
RUNNABLE
TERMINATED线程同步
多个线程改同一个变量会丢更新,因为 count++ 不是原子操作。用 synchronized 加锁,或改用 AtomicInteger、LongAdder 这类原子类。
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);
}
}10000
10000
true线程池
Executors.newFixedThreadPool(n) 创建固定大小线程池,submit 提交任务,shutdown 停止接收新任务。生产环境建议直接用 ThreadPoolExecutor 显式指定队列与拒绝策略。
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());
}
}3
true