Java多线程、线程池介绍及多线程间的协同

Java多线程是Java编程中的一个核心概念,它允许程序同时执行多个任务,从而提高程序的执行效率和响应速度。下面我将从线程的创建、线程的状态管理、线程的协作、线程池的使用、同步机制的实现以及并发控制的方法等几个方面来详细介绍Java多线程。

一、线程的创建

在Java中,创建线程主要有三种方式:

继承Thread类‌:
通过自定义一个类继承Thread类,并重写其run方法来实现线程的创建。在run方法中编写线程需要执行的代码。然后创建该类的实例,并调用其start方法来启动线程。

public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的代码
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

实现Runnable接口‌:
通过实现Runnable接口,并重写其run方法来实现线程的创建。这种方式的好处是避免了Java单继承的局限性。然后创建Runnable接口的实现类实例,将其作为参数传递给Thread类的构造函数来创建线程对象,并调用start方法启动线程。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行的代码
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

通过Callable和FutureTask创建线程‌:这种方式创建的线程可以返回值。首先需要创建Callable接口的实现类,并实现其call方法。然后创建Callable实现类的实例,并使用FutureTask类进行包装。最后,将FutureTask对象作为Thread对象的参数来启动新线程,并调用FutureTask对象的get方法获取子线程执行结束后的返回值。

二、线程的状态管理

线程在其生命周期中会经历不同的状态,包括新建(NEW)、可运行(RUNNABLE)、运行(RUNNING)、阻塞(BLOCKED)、等待(WAITING)、计时等待(TIMED_WAITING)和终止(TERMINATED)。

  • 新建状态‌:新创建了一个线程对象,但还没有调用start方法。
  • 可运行状态‌:线程对象创建后,其他线程调用了该对象的start方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权。
  • 运行状态‌:可运行状态的线程获得了CPU时间片,执行程序代码。
  • 阻塞状态‌:线程因为某种原因(如等待某个条件成立)而暂停执行,此时线程不会释放锁。
  • 等待状态‌:线程进入等待状态,等待其他线程的通知(如调用Object类的wait方法)。
  • 计时等待状态‌:线程在等待的同时设置了一个超时时间(如调用Thread类的sleep方法)。
  • 终止状态‌:线程执行完毕或异常退出。

三、线程池的使用

线程池是一种用于管理线程的机制,它可以方便地管理线程,减少内存的消耗,并复用线程。Java中的线程池主要由java.util.concurrent包提供。

  • 创建线程池‌:可以使用Executors类提供的静态方法来创建线程池,如newFixedThreadPool、newCachedThreadPool等。
  • 提交任务‌:使用线程池的submit方法提交任务,任务可以是Runnable接口的实现类或Callable接口的实现类。
  • 关闭线程池‌:使用线程池的shutdown方法关闭线程池,不再接受新任务,但会继续执行已提交的任务。shutdownNow方法则会尝试立即关闭线程池,并尝试停止正在执行的任务。

四、线程的协同

Java线程协同是指多个线程在执行过程中相互协作,共同完成某个任务。这通常涉及到线程之间的通信和同步。

1、基本概念
  1. 线程间的通信‌:

    • 线程间通过共享内存、阻塞队列、信号量等方式进行通信。
    • 线程可以调用某个对象的wait()方法,使自己进入等待状态,同时释放该对象上的锁。另一个线程可以调用相同对象的notify()或notifyAll()方法,唤醒一个或多个处于等待状态的线程。
  2. 线程间的同步

 ‌            synchronized关键字‌:可以用于方法或代码块,实现线程之间的互斥访问。

‌             volatile关键字‌:用于修饰变量,确保变量的可见性,但不能保证原子性。

 ‌            Lock接口‌:提供了更灵活的锁机制,如可重入锁(ReentrantLock)、读写锁(ReadWriteLock)等。

2、并发控制的方法

在Java多线程编程中,并发控制是非常重要的。Java提供了多种并发控制的方法,如信号量(Semaphore)、屏障(CyclicBarrier)、交换器(Exchanger)和条件变量(Condition)等。

  • 信号量‌:用于控制对共享资源的访问数量。
  • 屏障‌:用于让一组线程互相等待,直到所有线程都到达一个共同屏障点时再继续执行。
  • 交换器‌:用于在两个线程之间交换数据。
  • 条件变量‌:与Lock接口配合使用,用于实现线程之间的等待/通知机制。
3、线程协同的实现
  1. 共享内存‌:

    • 多个线程可以访问共享变量或数据结构,通过加锁和解锁来确保数据的一致性。
  2. 等待/通知机制‌:

    • 使用Object类的wait()和notify()/notifyAll()方法实现线程间的协作。
    • 示例代码:
      public class WaitNotifyExample {
          private static final Object lock = new Object();
          private static boolean flag = true;
      
          static class WaitThread implements Runnable {
              @Override
              public void run() {
                  synchronized (lock) {
                      while (flag) {
                          try {
                              lock.wait();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                      System.out.println("WaitThread is running");
                  }
              }
          }
      
          static class NotifyThread implements Runnable {
              @Override
              public void run() {
                  synchronized (lock) {
                      flag = false;
                      lock.notify();
                  }
              }
          }
      
          public static void main(String[] args) {
              Thread waitThread = new Thread(new WaitThread());
              Thread notifyThread = new Thread(new NotifyThread());
              waitThread.start();
              notifyThread.start();
          }
      }
      

  3. 阻塞队列‌:

    • 使用BlockingQueue接口实现线程安全的队列,支持在队尾插入元素和从队首移除元素。
    • 常用于生产者-消费者模式,实现线程间的协作。
  4. 信号量(Semaphore)‌:

    • 用于控制对共享资源的访问,通过acquire()和release()方法实现线程间的同步和协作。
  5. 倒计时门闩(CountDownLatch)‌:

    • 允许一个或多个线程等待其他线程完成操作,当计数器的值为0时,所有等待的线程将被释放。
    • 示例代码:
      import java.util.concurrent.CountDownLatch;
      
      public class CountDownLatchExample {
          public static void main(String[] args) throws InterruptedException {
              CountDownLatch latch = new CountDownLatch(2);
      
              new Thread(() -> {
                  try {
                      System.out.println("Thread A is running");
                      Thread.sleep(1000);
                      latch.countDown();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }).start();
      
              new Thread(() -> {
                  try {
                      System.out.println("Thread B is running");
                      Thread.sleep(1000);
                      latch.countDown();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }).start();
      
              latch.await();
              System.out.println("All tasks are done");
          }
      }
      

  6. 循环栅栏(CyclicBarrier)‌:

    • 允许一组线程互相等待,直到所有线程都到达某个屏障点。
    • 可以重复使用,支持线程间的协作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jackiendsc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值