【JAVA进阶篇教学】第六篇:Java线程中状态

简介: 【JAVA进阶篇教学】第六篇:Java线程中状态

博主打算从0-1讲解下java进阶篇教学,今天教学第六篇:Java线程中状态。    

理解并掌握线程的休眠、停止和挂起等操作是多线程编程中的重要内容。下面我将详细说明这些操作,并提供相应的代码案例。


一、线程休眠(Thread Sleep)

Thread.sleep()方法可以在任何线程中调用,包括主线程和子线程。它可以用于模拟等待、暂停执行或者降低CPU消耗等场景。但是需要注意的是,Thread.sleep()方法会暂停当前线程的执行,因此应该确保不会在关键代码段中调用,以避免影响程序的正常运行。


在Java中,可以使用Thread.sleep()方法来使当前线程休眠一段时间。该方法接受一个毫秒数作为参数,表示线程休眠的时间。

public class ThreadSleepExample {
    public static void main(String[] args) {
        System.out.println("Main thread starts.");
 
        // 创建一个新线程并启动
        Thread thread = new Thread(new Worker());
        thread.start();
 
        // 主线程休眠3秒钟
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // 主线程结束
        System.out.println("Main thread ends.");
    }
 
    static class Worker implements Runnable {
        @Override
        public void run() {
            System.out.println("Worker thread starts.");
            // Worker线程休眠2秒钟
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Worker thread ends.");
        }
    }
}


二、线程停止(Thread Stop)


线程停止通常应该由线程本身来控制。可以通过设置一个标志位来控制线程的执行状态,然后在适当的时机检查该标志位并退出线程。这样做可以保证线程的退出过程是安全和可控的。避免直接使用Thread.stop()方法来强制停止线程,因为这可能会导致线程处于不确定的状态,并可能导致数据不一致等问题。


在Java中,通常不推荐直接使用Thread.stop()方法来停止线程,因为这会导致线程处于不确定的状态,并且可能会导致数据不一致等问题。更安全的做法是使用标志位来控制线程的执行状态。

public class ThreadStopExample {
    private static volatile boolean running = true;
 
    public static void main(String[] args) {
        System.out.println("Main thread starts.");
 
        // 创建一个新线程并启动
        Thread thread = new Thread(new Worker());
        thread.start();
 
        // 主线程休眠3秒钟
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // 停止Worker线程
        running = false;
 
        // 主线程结束
        System.out.println("Main thread ends.");
    }
 
    static class Worker implements Runnable {
        @Override
        public void run() {
            System.out.println("Worker thread starts.");
            while (running) {
                // 执行任务
            }
            System.out.println("Worker thread ends.");
        }
    }
}

三、线程挂起(Thread Suspend 和 Thread Resume)

Thread.suspend()和Thread.resume()方法已经被标记为废弃,不推荐使用。如果确实需要在某些情况下使用这些方法,应该在合适的时机调用,并且谨慎处理线程的挂起和恢复过程。需要注意的是,这些方法可能会导致线程死锁和数据不一致等问题,因此应该尽量避免使用。


在Java中,可以使用Thread.suspend()方法将线程挂起,使用Thread.resume()方法将线程恢复。但是,这两个方法已经被标记为废弃,因为它们可能导致线程死锁和数据不一致等问题,不推荐使用。

public class ThreadSuspendResumeExample {
    public static void main(String[] args) {
        System.out.println("Main thread starts.");
 
        // 创建一个新线程并启动
        Thread thread = new Thread(new Worker());
        thread.start();
 
        // 主线程休眠3秒钟
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // 挂起Worker线程
        thread.suspend();
        System.out.println("Worker thread suspended.");
 
        // 主线程休眠3秒钟
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        // 恢复Worker线程
        thread.resume();
        System.out.println("Worker thread resumed.");
 
        // 主线程结束
        System.out.println("Main thread ends.");
    }
 
    static class Worker implements Runnable {
        @Override
        public void run() {
            System.out.println("Worker thread starts.");
            while (true) {
                // 执行任务
            }
        }
    }
}

尽管Thread.suspend()和Thread.resume()方法已经被标记为废弃,但是在某些特定的情况下,仍然可以使用它们。不过需要谨慎使用,以避免可能出现的问题。


四、线程等待(Object Wait)

在Java中,wait()方法是Object类的一个实例方法,用于让当前线程进入等待状态,同时释放对象的锁。当调用wait()方法时,当前线程会被挂起,直到其他线程调用了该对象的notify()或notifyAll()方法来唤醒它,或者等待指定的时间到达。


详细说明

  • 当调用wait()方法时,当前线程会进入对象的等待队列中,并释放对象的锁,允许其他线程访问该对象。
  • 调用wait()方法的线程会一直等待,直到被唤醒(通过notify()或notifyAll()方法),或者等待时间到达(如果提供了超时参数)。
  • 被唤醒的线程会重新进入对象的锁池中,等待获取对象的锁后继续执行。
  • 如果调用wait()方法的线程在等待过程中被中断,会抛出InterruptedException异常。


下面是一个使用wait()和notify()方法的示例,演示了如何实现简单的生产者-消费者模式:

public class ProducerConsumerExample {
    private static final int MAX_CAPACITY = 5;
    private static List<Integer> buffer = new ArrayList<>();
 
    public static void main(String[] args) {
        Thread producerThread = new Thread(new Producer());
        Thread consumerThread = new Thread(new Consumer());
 
        producerThread.start();
        consumerThread.start();
    }
 
    static class Producer implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (buffer) {
                    while (buffer.size() == MAX_CAPACITY) {
                        try {
                            buffer.wait(); // 缓冲区已满,生产者等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
 
                    int item = (int) (Math.random() * 100);
                    buffer.add(item);
                    System.out.println("Produced: " + item);
 
                    buffer.notifyAll(); // 唤醒所有消费者
                }
            }
        }
    }
 
    static class Consumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (buffer) {
                    while (buffer.isEmpty()) {
                        try {
                            buffer.wait(); // 缓冲区为空,消费者等待
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
 
                    int item = buffer.remove(0);
                    System.out.println("Consumed: " + item);
 
                    buffer.notifyAll(); // 唤醒所有生产者
                }
            }
        }
    }
}

在上面的示例中,生产者线程和消费者线程共享一个缓冲区buffer,当缓冲区为空时,消费者线程会调用wait()方法进入等待状态,直到生产者线程生产出新的数据并调用notifyAll()方法唤醒它。同样,当缓冲区已满时,生产者线程会调用wait()方法进入等待状态,直到消费者线程消费掉部分数据后调用notifyAll()方法唤醒它。


这样,通过使用wait()和notify()方法,可以实现生产者-消费者模式中的线程协作。

相关文章
|
1天前
|
Java
Java一分钟之-并发编程:线程间通信(Phaser, CyclicBarrier, Semaphore)
【5月更文挑战第19天】Java并发编程中,Phaser、CyclicBarrier和Semaphore是三种强大的同步工具。Phaser用于阶段性任务协调,支持动态注册;CyclicBarrier允许线程同步执行,适合循环任务;Semaphore控制资源访问线程数,常用于限流和资源池管理。了解其使用场景、常见问题及避免策略,结合代码示例,能有效提升并发程序效率。注意异常处理和资源管理,以防止并发问题。
23 2
|
1天前
|
安全 Java 容器
Java一分钟之-并发编程:线程安全的集合类
【5月更文挑战第19天】Java提供线程安全集合类以解决并发环境中的数据一致性问题。例如,Vector是线程安全但效率低;可以使用Collections.synchronizedXxx将ArrayList或HashMap同步;ConcurrentHashMap是高效线程安全的映射;CopyOnWriteArrayList和CopyOnWriteArraySet适合读多写少场景;LinkedBlockingQueue是生产者-消费者模型中的线程安全队列。注意,过度同步可能影响性能,应尽量减少共享状态并利用并发工具类。
16 2
|
1天前
|
Java 程序员 调度
Java中的多线程编程:基础知识与实践
【5月更文挑战第19天】多线程编程是Java中的一个重要概念,它允许程序员在同一时间执行多个任务。本文将介绍Java多线程的基础知识,包括线程的创建、启动和管理,以及如何通过多线程提高程序的性能和响应性。
|
2天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【5月更文挑战第18天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将了解线程池的基本概念,应用场景,以及如何优化线程池的性能。通过实例分析,我们将看到线程池如何提高系统性能,减少资源消耗,并提高系统的响应速度。
12 5
|
2天前
|
消息中间件 安全 Java
理解Java中的多线程编程
【5月更文挑战第18天】本文介绍了Java中的多线程编程,包括线程和多线程的基本概念。Java通过继承Thread类或实现Runnable接口来创建线程,此外还支持使用线程池(如ExecutorService和Executors)进行更高效的管理。多线程编程需要注意线程安全、性能优化和线程间通信,以避免数据竞争、死锁等问题,并确保程序高效运行。
|
2天前
|
存储 Java
【Java】实现一个简单的线程池
,如果被消耗完了就说明在规定时间内获取不到任务,直接return结束线程。
11 0
|
2天前
|
安全 Java 容器
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第18天】随着多核处理器的普及,并发编程变得越来越重要。Java提供了丰富的并发编程工具,如synchronized关键字、显式锁Lock、原子类、并发容器等。本文将深入探讨Java并发编程的核心概念,包括线程安全、死锁、资源竞争等,并分享一些性能优化的技巧。
|
2天前
|
安全 Java 开发者
Java中的多线程编程:理解与实践
【5月更文挑战第18天】在现代软件开发中,多线程编程是提高程序性能和响应速度的重要手段。Java作为一种广泛使用的编程语言,其内置的多线程支持使得开发者能够轻松地实现并行处理。本文将深入探讨Java多线程的基本概念、实现方式以及常见的并发问题,并通过实例代码演示如何高效地使用多线程技术。通过阅读本文,读者将对Java多线程编程有一个全面的认识,并能够在实际开发中灵活运用。
|
2天前
|
算法 Java 程序员
Java中的线程同步与并发控制
【5月更文挑战第18天】随着计算机技术的不断发展,多核处理器的普及使得多线程编程成为提高程序性能的关键。在Java中,线程是实现并发的一种重要手段。然而,线程的并发执行可能导致数据不一致、死锁等问题。本文将深入探讨Java中线程同步的方法和技巧,以及如何避免常见的并发问题,从而提高程序的性能和稳定性。
|
3天前
|
存储 安全 Java
Java多线程基础知识总结,36岁老码农现身说法
Java多线程基础知识总结,36岁老码农现身说法