java多线程(超具体!)

打印 上一主题 下一主题

主题 895|帖子 895|积分 2685

Java 的多线程是一种允许在一个程序中同时运行多个线程的技术。每个线程是独立的执行路径,可以并发执行,从而提高程序的效率和响应能力。
1. 线程基础

Java 中的线程可以通过继承 Thread 类或实现 Runnable 接口来创建和管理。
1.1 继承 Thread 类
  1. class MyThread extends Thread {
  2.     public void run() {
  3.         System.out.println("Thread is running...");
  4.     }
  5. }
  6. public class TestThread {
  7.     public static void main(String[] args) {
  8.         MyThread t1 = new MyThread();
  9.         t1.start(); // 启动线程
  10.     }
  11. }
复制代码
run() 方法包罗线程执行的代码,而 start() 方法用于启动新线程。
1.2 实现 Runnable 接口
  1. class MyRunnable implements Runnable {
  2.     public void run() {
  3.         System.out.println("Thread is running...");
  4.     }
  5. }
  6. public class TestRunnable {
  7.     public static void main(String[] args) {
  8.         MyRunnable myRunnable = new MyRunnable();
  9.         Thread t1 = new Thread(myRunnable);
  10.         t1.start(); // 启动线程
  11.     }
  12. }
复制代码
通过实现 Runnable 接口的方式可以更机动地共享资源。
2. 线程的生命周期

线程在其生命周期中经历以下状态:

  • 新建(New): 线程对象被创建,但还没有调用 start() 方法。
  • 停当(Runnable): 线程对象调用了 start() 方法,等待 CPU 调度。
  • 运行(Running): 线程获得 CPU,开始执行 run() 方法的代码。
  • 壅闭(Blocked): 线程由于某种缘故原由(如等待资源、睡眠)被挂起。
  • 死亡(Dead): 线程执行完 run() 方法,或者因异常退出。
3. 线程控制

Java 提供了一些方法来控制线程的执行:

  • sleep(long millis):让当火线程睡眠指定的毫秒数。
  • join():等待该线程终止,也就是说等待当前的线程竣事, 才会继续执行下面的代码
  • yield():停息当火线程,让出 CPU 给其他线程。
  • interrupt():中断线程。
4. 线程同步

多线程程序中大概会出现多个线程同时访问共享资源的情况,导致数据不划一的问题。为相识决这个问题,可以利用同步技术。
4.1. ReentrantLock

ReentrantLock 提供了比 synchronized 更加机动的锁机制,可以显式地锁定息争锁。
  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. public class ReentrantLockExample {
  4.     private final Lock lock = new ReentrantLock();
  5.     private int count = 0;
  6.     public void increment() {
  7.         lock.lock();
  8.         try {
  9.             count++;
  10.         } finally {
  11.             lock.unlock();
  12.         }
  13.     }
  14.     public int getCount() {
  15.         return count;
  16.     }
  17. }
复制代码
4.2. ReadWriteLock

ReadWriteLock 提供了一对锁,一个用于读操作,一个用于写操作。这允许多个读线程同时访问共享资源,但在写线程访问时会独占锁。
  1. import java.util.concurrent.locks.ReadWriteLock;
  2. import java.util.concurrent.locks.ReentrantReadWriteLock;
  3. public class ReadWriteLockExample {
  4.     private final ReadWriteLock lock = new ReentrantReadWriteLock();
  5.     private int count = 0;
  6.     public void increment() {
  7.         lock.writeLock().lock();
  8.         try {
  9.             count++;
  10.         } finally {
  11.             lock.writeLock().unlock();
  12.         }
  13.     }
  14.     public int getCount() {
  15.         lock.readLock().lock();
  16.         try {
  17.             return count;
  18.         } finally {
  19.             lock.readLock().unlock();
  20.         }
  21.     }
  22. }
复制代码
4.3 synchronized

在方法前利用 synchronized 关键字,确保同一时间只有一个线程可以执行该方法。
  1. class Counter {
  2.     private int count = 0;
  3.     public synchronized void increment() {
  4.         count++;
  5.     }
  6.     public int getCount() {
  7.         return count;
  8.     }
  9. }
复制代码
4.4 同步块

同步块可以更机动地控制需要同步的代码块,而不是整个方法。
  1. class Counter {
  2.     private int count = 0;
  3.     public void increment() {
  4.         synchronized (this) {
  5.             count++;
  6.         }
  7.     }
  8.     public int getCount() {
  9.         return count;
  10.     }
  11. }
复制代码
4.5 注意事项

下面代码中的写法, 不能保证同一时间只有一个线程可以执行该方法。
由于 4.3 和 4.4 中 synchronized 的写法是根据 this 来保证同一时间只有一个线程可以执行, 但是他们的 this 是不同的。(把 "需要替换的" 换成解释上的就可以 "保证同一时间只有一个线程可以执行")
  1. class Worker implements Runnable {
  2.     public static int cnt = 0;
  3.     @Override
  4.     public synchronized void run() {
  5.         for (int i = 0; i < 100000; i ++) {
  6.             cnt ++;
  7.         }
  8.     }
  9. }
  10. public class Main {
  11.     public static void main(String[] args) throws InterruptedException {
  12.    
  13. //        Worker worker = new Worker();
  14. //        Thread t1 = new Thread(worker);
  15. //        Thread t2 = new Thread(worker);
  16.         Thread t1 = new Thread(new Worker());        // 需要替换
  17.         Thread t2 = new Thread(new Worker());        // 需要替换
  18.         t1.start();
  19.         t2.start();
  20.         t1.join();
  21.         t2.join();
  22.         System.out.println(Worker.cnt);
  23.     }
  24. }
复制代码
固然, 4.4 的代码也可以写成下面这样,这样他就是根据 lock 这个对象来保证同步的, java中的对象都可以当作lock
  1. class Counter {
  2.         public static final Object lock = new Object();
  3.     private int count = 0;
  4.     public void increment() {
  5.         synchronized (lock ) {
  6.             count++;
  7.         }
  8.     }
  9.     public int getCount() {
  10.         return count;
  11.     }
  12. }
复制代码
5. 线程通信

Java 提供了 wait(), notify(), notifyAll() 方法来实现线程间的通信。

  • wait():让当火线程等待,直到其他线程调用 notify() 或 notifyAll()。
  • notify():唤醒一个正在等待的线程。
  • notifyAll():唤醒所有正在等待的线程。
6. 线程池

利用线程池可以有效地管理和复用线程,淘汰创建和销毁线程的开销。Java 提供了 Executor 框架来管理线程池。
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. public class TestThreadPool {
  4.     public static void main(String[] args) {
  5.         ExecutorService executor = Executors.newFixedThreadPool(5);
  6.         for (int i = 0; i < 10; i++) {
  7.             executor.execute(new MyRunnable());
  8.         }
  9.         executor.shutdown();
  10.     }
  11. }
复制代码
7. 高级线程工具

Java 提供了很多高级线程工具,如 Semaphore, CountDownLatch, CyclicBarrier 等,用于复杂的线程协调和同步。
7.1 Semaphore

信号量控制同时访问特定资源的线程数量。
  1. import java.util.concurrent.Semaphore;
  2. public class TestSemaphore {
  3.     private static final Semaphore semaphore = new Semaphore(3);
  4.     public static void main(String[] args) {
  5.         for (int i = 0; i < 10; i++) {
  6.             new Thread(new Task()).start();
  7.         }
  8.     }
  9.     static class Task implements Runnable {
  10.         public void run() {
  11.             try {
  12.                 semaphore.acquire();
  13.                 System.out.println("Thread " + Thread.currentThread().getName() + " is accessing the resource.");
  14.                 Thread.sleep(2000);
  15.                 semaphore.release();
  16.             } catch (InterruptedException e) {
  17.                 e.printStackTrace();
  18.             }
  19.         }
  20.     }
  21. }
复制代码
7.2 CountDownLatch

允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
  1. import java.util.concurrent.CountDownLatch;
  2. public class TestCountDownLatch {
  3.     private static final int THREAD_COUNT = 3;
  4.     private static final CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
  5.     public static void main(String[] args) {
  6.         for (int i = 0; i < THREAD_COUNT; i++) {
  7.             new Thread(new Task()).start();
  8.         }
  9.         try {
  10.             latch.await(); // 主线程等待所有子线程完成
  11.             System.out.println("All threads have finished.");
  12.         } catch (InterruptedException e) {
  13.             e.printStackTrace();
  14.         }
  15.     }
  16.     static class Task implements Runnable {
  17.         public void run() {
  18.             System.out.println("Thread " + Thread.currentThread().getName() + " is working.");
  19.             latch.countDown(); // 计数器减一
  20.         }
  21.     }
  22. }
复制代码
结论

Java 多线程是一个强盛且复杂的技术,需要深入明白和警惕利用,以制止潜在的并发问题和死锁情况。通过合理地利用线程同步、线程通信和线程池等工具,可以编写高效且安全的多线程应用程序。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

缠丝猫

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表