- 线程的基本概念与创建方式
-
-
线程的概念:
在Java中,线程是程序中的一个独立执行路径。每个Java应用程序至少有一个主线程,它是由Java虚拟机启动的。在多线程编程中,可以创建额外的线程来并行执行任务。
-
线程的生命周期:
-
新建(New):线程对象创建后,处于新建状态。
-
就绪(Runnable):线程启动后,等待CPU调度。
-
运行(Running):线程被CPU调度,开始执行任务。
-
阻塞(Blocked):线程等待某种条件或事件,进入阻塞状态。
-
终止(Terminated):线程执行完成,进入终止状态。
-
-
-
创建线程的方式:
Java中有两种主要的创建线程的方式:
-
继承Thread类:
-
示例代码:
class MyThread extends Thread { @Override public void run() { System.out.println("Thread is running..."); } } public class Main { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // 启动线程 } }
在这个例子中,我们通过继承
Thread
类并重写run()
方法来创建线程。 -
-
实现Runnable接口:
-
示例代码:
class MyRunnable implements Runnable { @Override public void run() { System.out.println("Runnable is running..."); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); // 启动线程 } }
通过实现
Runnable
接口的run()
方法,我们将线程逻辑传递给Thread
对象,这种方式更加灵活。 -
-
2. Runnable接口与Thread类
-
Thread类与Runnable接口的区别:
-
继承Thread类直接创建线程,但由于Java是单继承的,继承
Thread
会限制类的继承能力。 -
实现Runnable接口更加推荐,因为它可以保持类的扩展性,同时支持多线程。
-
-
使用示例:
假设有一个任务需要重复执行100次,创建多个线程来同时完成这个任务:
class Task implements Runnable { private String taskName; public Task(String name) { this.taskName = name; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(taskName + " - " + i); } } } public class Main { public static void main(String[] args) { Thread thread1 = new Thread(new Task("Task 1")); Thread thread2 = new Thread(new Task("Task 2")); thread1.start(); thread2.start(); } }
3. 线程同步与锁机制
-
线程安全问题:
当多个线程同时访问共享资源时,可能会产生数据不一致的问题。这时需要使用线程同步机制来保证线程的安全性。
-
同步方法与同步块:
-
同步方法:可以通过在方法前加
synchronized
关键字,保证同一时间只有一个线程可以执行该方法。-
示例代码:
class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }
-
-
同步块:可以在代码块前加
synchronized
关键字,锁定特定对象。-
示例代码:
class Counter { private int count = 0; private final Object lock = new Object(); public void increment() { synchronized (lock) { count++; } } public int getCount() { return count; } }
-
-
-
锁机制:
Java 还提供了更灵活的
Lock
接口,通过ReentrantLock
类实现:class Counter { private int count = 0; private final ReentrantLock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { return count; } }
4. 线程池的概念与使用(Executor框架)
-
什么是线程池?
线程池是一种重用线程的机制,通过提前创建一组线程来处理任务,避免频繁创建和销毁线程带来的开销。
-
使用ExecutorService来管理线程池:
ExecutorService executor = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { executor.submit(new Task("Task " + i)); } executor.shutdown(); // 关闭线程池
在这里,
newFixedThreadPool(3)
创建了一个包含3个线程的线程池,接着提交了5个任务给线程池执行。
5. 并发包中的高级工具类
-
-
CyclicBarrier:
允许一组线程互相等待,直到到达某个公共屏障点。
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached the barrier")); for (int i = 0; i < 3; i++) { new Thread(() -> { try { System.out.println("Thread ready"); barrier.await(); // 等待其他线程 } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }).start();
-
Semaphore:
控制访问资源的并发线程数。
Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i++) { new Thread(() -> { try { semaphore.acquire(); // 获取许可 System.out.println("Thread running"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 释放许可 } }).start(); }
-
CountDownLatch:
用于使一个或多个线程等待其他线程完成某些操作。
CountDownLatch latch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println("Task completed"); latch.countDown(); }).start(); } latch.await(); // 等待其他线程完成 System.out.println("All tasks completed");
-