您的位置:首页 > 教育 > 培训 > JAVA多线程

JAVA多线程

2025/7/14 1:26:06 来源:https://blog.csdn.net/weixin_38301116/article/details/141886578  浏览:    关键词:JAVA多线程

1、多线程的状态

  • 线程在一定条件下,状态会发生变化。线程一共有以下几种状态
  1. 新建状态(New): 创建一个新的线程对象
  2. 就绪状态(Runnable): 线程对象创建后,调用该对象的start()方法,改线程就进入到就绪状态。这意味着线程已经准备好执行,等待系统分配处理器资源。
  3. 运行(Running) :线程获得了处理器资源,开始执行run()方法中的代码。这是线程处于活动状态的阶段。
  4. 阻塞(Blocked):线程在等待某个条件满足时进入阻塞状态。例如,线程可能在等待I/O操作完成或者等待获取锁。
  5. 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
  • 代码示例1
  • 多线程的几种状态 (无阻塞)
public class MyThread{public static void main(String[] args) throws Exception {Thread thread=new Thread(() -> {System.out.println("线程进入可运行状态");try {Thread.sleep(1000); // 让线程休眠1秒,模拟执行任务} catch (InterruptedException e) {throw new RuntimeException(e);}});// 打印线程初始状态System.out.println("线程初始状态: " + thread.getState());// 启动线程thread.start();// 打印线程可运行状态System.out.println("线程可运行状态: " + thread.getState());// 主线程等待子线程执行完毕thread.join();// 打印线程终止状态System.out.println("线程终止状态: " + thread.getState());}
}
  • 代码示例2
  • 线程的几种状态(包含阻塞)
public class MyThread {private static Lock lock = new ReentrantLock();private static Condition condition = lock.newCondition();private static boolean flag = false;public static void main(String[] args) throws Exception {Thread thread1 = new Thread(() -> {try {System.out.println("线程1进入可运行状态");lock.lock();while (!flag) {condition.await(); // 等待条件满足}System.out.println("线程1继续执行");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}});Thread thread2 = new Thread(() -> {try {System.out.println("线程2进入可运行状态");Thread.sleep(3000);lock.lock();flag = true;condition.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}});// 打印线程初始状态System.out.println("线程1初始状态: " + thread1.getState());System.out.println("线程2初始状态: " + thread2.getState());// 启动线程thread1.start();thread2.start();// 打印线程可运行状态System.out.println("线程1可运行状态: " + thread1.getState());System.out.println("线程2可运行状态: " + thread2.getState());try {// 主线程等待子线程执行完毕thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 打印线程终止状态System.out.println("线程1终止状态: " + thread1.getState());System.out.println("线程2终止状态: " + thread2.getState());}
}
输出结果:
线程1初始状态: NEW
线程2初始状态: NEW
线程1可运行状态: RUNNABLE
线程2可运行状态: RUNNABLE
线程1进入可运行状态
线程2进入可运行状态
线程1继续执行
线程1终止状态: TERMINATED
线程2终止状态: TERMINATED
--------------------------------------
public class MyThread {public static void main(String[] args) {Object lock = new Object();Thread thread1 = new Thread(() -> {synchronized (lock) {try {System.out.println("线程1等待");lock.wait();System.out.println("线程1继续执行");} catch (InterruptedException e) {e.printStackTrace();}}});Thread thread2 = new Thread(() -> {synchronized (lock) {System.out.println("线程2唤醒线程1");lock.notify();}});thread1.start();thread2.start();}
}输出结果:
线程1等待
线程2唤醒线程1
线程1继续执行

2、 线程中常用的方法

  • Thread类的几个常用的方法
  1. start():开始执行线程的方法,java虚拟机会调用线程内的run()方法;
  2. yield():yield在英语里有放弃的意思,同样,这里的yield()指的是当前线程愿意让出对当前处理器的占用。这里需要注意的是,就算当前线程调用了yield()方法,程序在调度的时候,也还有可能继续运行这个线程的;
  3. sleep():静态方法,使当前线程睡眠一段时间;
  4. join():使当前线程等待另一个线程执行完毕之后再继续执行,内部调用的是Object类的wait方法实现的;
  • Object类的几个常用的方法
  1. wait():当一个线程调用一个对象的 wait() 方法时,它会释放该对象的锁,然后进入等待状态。直到其他线程调用相同对象的 notify() 或 notifyAll() 方法来唤醒它。被唤醒后,线程会尝试重新获取对象的锁,并在成功获取锁之后继续执行。如果在调用 wait() 之前没有持有对象的锁,那么会抛出 IllegalMonitorStateException。
  2. notify(): 当一个线程调用一个对象的 notify() 方法时,它会随机唤醒在该对象上等待的一个线程(如果有的话)。被唤醒的线程将从等待池中移除,并尝试重新获取对象的锁。如果多个线程在等待,只有一个线程会被唤醒。如果没有线程在等待,那么调用 notify() 没有任何效果。
  3. notifyAll():与 notify() 类似,但不同之处在于它会唤醒所有在该对象上等待的线程。这些线程都将从等待池中移除,并尝试重新获取对象的锁。如果没有线程在等待,那么调用 notifyAll() 同样没有任何效果。
    4.wait(), notify(), 和 notifyAll() 必须在同步块或同步方法中使用,因为它们依赖于对象的内置锁。此外,为了避免死锁和活锁等问题,通常使用更高级的并发工具,如 java.util.concurrent 包中的 Lock 和 Condition。

3、线程中添加返回值

  • 使用Callable接口和FutureTask类。Callable接口允许你定义一个任务,该任务在执行完成后可以返回一个结果。FutureTask类是一个实现了Runnable接口的类,它接受一个Callable对象作为参数,并在调用run()方法时执行该任务
    示例代码:
public class MyThread implements Callable<Integer> {@Overridepublic Integer call() throws Exception {Thread.sleep(1000);return 2;}public static void main(String[] args) throws ExecutionException, InterruptedException {//方法1ExecutorService executorService= Executors.newSingleThreadExecutor();MyThread myThread=new MyThread();Future<Integer> submit = executorService.submit(myThread);// 注意调用get方法会阻塞当前线程,直到得到结果。// 所以实际编码中建议使用可以设置超时时间的重载get方法。System.out.println(submit.get());//方法2ExecutorService executor = Executors.newCachedThreadPool();FutureTask<Integer> futureTask = new FutureTask<>(new MyThread());executor.submit(futureTask);System.out.println(futureTask.get());}
}

3、线程间通信

  • Java多线程的等待/通知机制是基于Object类的wait()方法和notify(), notifyAll()方法来实现的
public class MyThread{private static volatile int signal = 0;static class ThreadA implements Runnable {@Overridepublic void run() {while (signal < 5) {if (signal % 2 == 0) {System.out.println("threadA: " + signal);synchronized (this) {signal++;}}}}}static class ThreadB implements Runnable {@Overridepublic void run() {while (signal < 5) {if (signal % 2 == 1) {System.out.println("threadB: " + signal);synchronized (this) {signal = signal + 1;}}}}}public static void main(String[] args) throws InterruptedException {new Thread(new ThreadA()).start();Thread.sleep(1000);new Thread(new ThreadB()).start();}
}
  • 使用volatile关键字
public class MyThread{private static volatile boolean flag = false;public static void main(String[] args) {Thread thread1 = new Thread(() -> {while (!flag) {// 等待flag变为true}System.out.println("当前flag:"+flag);});Thread thread2 = new Thread(() -> {try {Thread.sleep(1000); // 模拟一些操作} catch (InterruptedException e) {e.printStackTrace();}flag = true; // 修改flag的值});thread1.start();thread2.start();}
}
  • 使用join
public class MyThread{public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {System.out.println("我是子线程,我先睡一秒");Thread.sleep(1000);System.out.println("我是子线程,我睡完了一秒");} catch (InterruptedException e) {e.printStackTrace();}});thread.start();thread.join();System.out.println("main结束");}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com