第五章:Java高级特性 第四节 多线程编程

  1.  线程的基本概念与创建方式
      • 线程的概念

        在Java中,线程是程序中的一个独立执行路径。每个Java应用程序至少有一个主线程,它是由Java虚拟机启动的。在多线程编程中,可以创建额外的线程来并行执行任务。

        • 线程的生命周期

          • 新建(New):线程对象创建后,处于新建状态。

          • 就绪(Runnable):线程启动后,等待CPU调度。

          • 运行(Running):线程被CPU调度,开始执行任务。

          • 阻塞(Blocked):线程等待某种条件或事件,进入阻塞状态。

          • 终止(Terminated):线程执行完成,进入终止状态。

      • 创建线程的方式

        Java中有两种主要的创建线程的方式:

        1. 继承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()方法来创建线程。

        2. 实现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. 线程同步与锁机制

      • 线程安全问题

        当多个线程同时访问共享资源时,可能会产生数据不一致的问题。这时需要使用线程同步机制来保证线程的安全性。

      • 同步方法与同步块

        1. 同步方法:可以通过在方法前加synchronized关键字,保证同一时间只有一个线程可以执行该方法。

          • 示例代码

            class Counter {
                private int count = 0;
            ​
                public synchronized void increment() {
                    count++;
                }
            ​
                public int getCount() {
                    return count;
                }
            }
        2. 同步块:可以在代码块前加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");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱掉发的小龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值