Java 多线程实例详解(二)
本文是Java多线程实例系列的第二篇,将进一步介绍Java多线程的实现方式以及相关应用的代码实例。
线程的生命周期
Java线程有5种状态:
- 新建状态(New):当线程被创建时,它处于新建状态。
- 就绪状态(Runnable):线程获得了CPU资源,并可以执行,但它还未开始执行它的代码。
- 运行状态(Running):线程正在执行它的代码。
- 阻塞状态(Blocked):线程暂时停止执行,通常是等待某个事件的发生,例如输入输出操作或者等待某个锁的释放。
- 终止状态(Terminated):线程已经执行完它的代码或者出现了异常而异常终止。
线程的实现方式
Java实现多线程有两种方式:
方式一:继承Thread类
继承Thread类的方式实现多线程需要重写run()方法,并通过start()方法启动线程。
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread1: " + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.start();
for (int i = 0; i < 10; i++) {
System.out.println("Main: " + i);
}
}
}
方式二:实现Runnable接口
实现Runnable接口的方式实现多线程需要实现run()方法,并通过Thread类的构造方法传入Runnable对象,再通过start()方法启动线程。
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread2: " + i);
}
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread2 = new Thread(runnable);
thread2.start();
for (int i = 0; i < 10; i++) {
System.out.println("Main: " + i);
}
}
}
线程的常用操作方法
Java提供了一些常用的线程操作方法:
- wait()方法:线程在执行wait()方法时会进入阻塞状态,直到其他线程调用notify()方法或notifyAll()方法才能唤醒它。
- notify()方法:唤醒处于wait()方法阻塞状态的线程中的一个线程。
- notifyAll()方法:唤醒处于wait()方法阻塞状态的所有线程。
- sleep()方法:使线程暂停一段时间,单位是毫秒,可避免CPU无限制地独占线程。
示例一:wait()与notify()方法的应用
wait()方法与notify()方法可以协调不同线程的执行,例如下面的示例:
public class ShareData {
private int count;
private boolean flag;
public synchronized void put(int count) {
if(flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.count = count;
System.out.println("生产者生产:" + count);
flag = true;
notify();
}
public synchronized void get() {
if(!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费:" + count);
flag = false;
notify();
}
}
public class Producer implements Runnable {
private ShareData shareData;
public Producer(ShareData shareData) {
this.shareData = shareData;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
shareData.put(i);
}
}
}
public class Consumer implements Runnable {
private ShareData shareData;
public Consumer(ShareData shareData) {
this.shareData = shareData;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
shareData.get();
}
}
}
public class Main {
public static void main(String[] args) {
ShareData shareData = new ShareData();
new Thread(new Producer(shareData)).start();
new Thread(new Consumer(shareData)).start();
}
}
以上示例中,生产者线程和消费者线程并不是依次执行,而是在满足条件时交替执行。这是通过wait()方法和notify()方法的配合实现的。
示例二:sleep()方法的应用
一些场景下需要暂停线程一段时间。例如,可以通过调用sleep()方法,模拟一个任务的执行时间,目的是更好地测试并发运行程序的效果。
public class SleepTask implements Runnable {
private String name;
public SleepTask(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name + " is running.");
try {
Thread.sleep(new Random().nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " is done.");
}
}
public class Main {
public static void main(String[] args) {
String[] tasks = {"task1", "task2", "task3", "task4", "task5"};
for (String task : tasks) {
new Thread(new SleepTask(task)).start();
}
}
}
sleep()方法的本质是让一个线程暂停执行,让出CPU资源,但不释放锁。假设在一段时间内,只有一个线程处于可执行状态,那么CPU资源将会一直被这个线程所占用,而其他线程只能等待。这时,就需要通过协作式的多线程编程,让当前线程卸载CPU资源,让其他线程能够执行。
结论
通过以上实例说明,在 Java中实现多线程的机制很灵活,有继承Thread类的方式,也有实现Runnable接口的方式,可以通过wait()方法和notify()方法适应不同的场景,利用sleep()方法来模拟线程执行时间。但同时,多线程编程也对线程安全问题提出了更高的要求,需要我们深入理解线程的执行机制及相关问题,进而对多线程程序进行优化。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 多线程实例详解(二) - Python技术站