Java多线程基础入门

2024/1/15

# Java多线程基础入门

点击勘误issues (opens new window),哪吒感谢大家的阅读

# 1. 什么是多线程

# 1.1 线程的概念

线程是程序执行的最小单位,一个进程可以包含多个线程。在Java中,每个线程都有自己的程序计数器、虚拟机栈和本地方法栈,但共享堆内存和方法区。

# 1.2 多线程的优势

  • 提高程序响应性:用户界面不会因为后台任务而卡顿
  • 充分利用CPU资源:多核CPU可以并行执行多个线程
  • 提高程序吞吐量:并发处理多个任务
  • 改善程序结构:将复杂任务分解为多个简单的并发任务

# 2. 创建线程的方式

# 2.1 继承Thread类

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        
        thread1.setName("线程1");
        thread2.setName("线程2");
        
        thread1.start();
        thread2.start();
    }
}

# 2.2 实现Runnable接口

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        
        Thread thread1 = new Thread(runnable, "线程1");
        Thread thread2 = new Thread(runnable, "线程2");
        
        thread1.start();
        thread2.start();
    }
}

# 2.3 实现Callable接口

import java.util.concurrent.*;

public class MyCallable implements Callable<String> {
    private String name;
    
    public MyCallable(String name) {
        this.name = name;
    }
    
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + ": " + i);
            Thread.sleep(1000);
        }
        return name + "执行完成";
    }
    
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        
        Future<String> future1 = executor.submit(new MyCallable("任务1"));
        Future<String> future2 = executor.submit(new MyCallable("任务2"));
        
        try {
            System.out.println(future1.get());
            System.out.println(future2.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}

# 2.4 使用Lambda表达式

public class LambdaThread {
    public static void main(String[] args) {
        // 使用Lambda表达式创建线程
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Lambda线程1: " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Lambda线程2: " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread1.start();
        thread2.start();
    }
}

# 3. 线程的生命周期

# 3.1 线程状态

Java线程有以下几种状态:

  • NEW:新建状态,线程被创建但还未调用start()方法
  • RUNNABLE:可运行状态,包括正在运行和等待CPU调度
  • BLOCKED:阻塞状态,等待获取锁
  • WAITING:等待状态,等待其他线程的通知
  • TIMED_WAITING:超时等待状态,在指定时间内等待
  • TERMINATED:终止状态,线程执行完毕

# 3.2 状态转换示例

public class ThreadStateDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("线程开始执行");
                Thread.sleep(2000);
                System.out.println("线程执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        System.out.println("创建后状态: " + thread.getState()); // NEW
        
        thread.start();
        System.out.println("启动后状态: " + thread.getState()); // RUNNABLE
        
        Thread.sleep(500);
        System.out.println("睡眠中状态: " + thread.getState()); // TIMED_WAITING
        
        thread.join();
        System.out.println("结束后状态: " + thread.getState()); // TERMINATED
    }
}

# 4. 线程的基本操作

# 4.1 线程优先级

public class ThreadPriorityDemo {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("高优先级线程: " + i);
            }
        });
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("低优先级线程: " + i);
            }
        });
        
        thread1.setPriority(Thread.MAX_PRIORITY); // 10
        thread2.setPriority(Thread.MIN_PRIORITY); // 1
        
        thread1.start();
        thread2.start();
    }
}

# 4.2 守护线程

public class DaemonThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread daemonThread = new Thread(() -> {
            while (true) {
                System.out.println("守护线程正在运行...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
        
        daemonThread.setDaemon(true); // 设置为守护线程
        daemonThread.start();
        
        Thread.sleep(3000);
        System.out.println("主线程结束");
        // 主线程结束后,守护线程也会自动结束
    }
}

# 4.3 线程中断

public class ThreadInterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("线程正在运行...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("线程被中断");
                    Thread.currentThread().interrupt(); // 重新设置中断标志
                    break;
                }
            }
            System.out.println("线程结束");
        });
        
        thread.start();
        Thread.sleep(3000);
        thread.interrupt(); // 中断线程
        thread.join();
    }
}

# 5. 线程安全问题

# 5.1 竞态条件示例

public class RaceConditionDemo {
    private static int counter = 0;
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter++;
            }
        });
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter++;
            }
        });
        
        thread1.start();
        thread2.start();
        
        thread1.join();
        thread2.join();
        
        System.out.println("最终结果: " + counter); // 可能不是20000
    }
}

# 5.2 使用synchronized解决

public class SynchronizedDemo {
    private static int counter = 0;
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (lock) {
                    counter++;
                }
            }
        });
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (lock) {
                    counter++;
                }
            }
        });
        
        thread1.start();
        thread2.start();
        
        thread1.join();
        thread2.join();
        
        System.out.println("最终结果: " + counter); // 确保是20000
    }
}

# 6. 总结

本文介绍了Java多线程的基础知识,包括:

  1. 线程创建方式:继承Thread类、实现Runnable接口、实现Callable接口、使用Lambda表达式
  2. 线程生命周期:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
  3. 线程基本操作:优先级设置、守护线程、线程中断
  4. 线程安全问题:竞态条件和synchronized解决方案

掌握这些基础知识是学习Java并发编程的重要基础。在实际开发中,还需要深入学习线程池、锁机制、并发容器等高级主题。

# 参考资料