Java多线程:基础详解攻略
什么是线程?
在计算机科学中,线程是指一个进程内部的单个执行流程。一个进程可以拥有多个线程,各个线程共享该进程的内存空间和系统资源,但每个线程拥有自己的程序计数器(PC)、栈和局部变量等。因此,多线程可以使程序在并发情况下更高效地运行。
如何创建线程?
Java提供了两种方式来创建线程:
1.继承Thread类
在Java中,我们可以通过扩展Thread类的方式来创建新线程。具体实现方式如下:
class MyThread extends Thread {
public void run() {
// 线程执行的代码
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
在上述代码中,我们定义了一个继承自Thread类的MyThread类,并重写了其run()方法。在main()方法中,我们创建了MyThread类实例并调用其start()方法,这将启动一个新线程并执行MyThread类中定义的run()方法。
2.实现Runnable接口
Java中另一种创建线程的方式是实现Runnable接口。具体实现方式如下:
class MyRunnable implements Runnable {
public void run() {
// 线程执行的代码
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
在上述代码中,我们定义了一个实现了Runnable接口的MyRunnable类,并重写了其run()方法。在main()方法中,我们创建了MyRunnable类实例和一个Thread类实例,并将MyRunnable实例作为参数传递给Thread类的构造函数。最后,调用Thread类的start()方法,启动一个新线程并执行MyRunnable类中的run()方法。
线程生命周期
线程在其生命周期中会经历以下5个状态:
1.新建状态(New)
当线程对象被创建时,它处于新建状态。此时,还未开始执行该线程的代码。
2.运行状态(Runnable)
当调用线程的start()方法后,该线程进入运行状态。此时,该线程正在执行其run()方法或等待CPU分配时间片来执行。
3.阻塞状态(Blocked)
当线程因为某些原因(如等待I/O、等待获取一个锁、等待线程结束等)而暂时停止时,它将变为阻塞状态。此时,该线程不会消耗CPU时间,直到它重新进入运行状态。
public class Main {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock) {
lock.notify();
}
});
thread1.start();
Thread.sleep(500);
thread2.start();
thread1.join();
thread2.join();
}
}
在上述代码中,我们创建了两个线程,分别为thread1和thread2。在thread1的run()方法中,我们使用synchronized关键字锁定了一个对象lock,然后调用lock.wait()方法来使线程进入阻塞状态。在thread2的run()方法中,我们同样使用synchronized关键字锁定了对象lock,然后调用lock.notify()方法,唤醒一个在lock上等待的线程。最后,在main()方法中,我们启动两个线程并让它们执行完毕。
4.等待状态(Waiting)
当线程因为某些原因(如执行了Object.wait()、Thread.join()、LockSupport.park()等方法)而等待时,它进入等待状态。此时,线程不会被分配CPU时间,也不会去尝试获取任何锁。
5.结束状态(Terminated)
当线程run()方法运行结束时,或者因为异常或中断而结束运行时,该线程进入结束状态。
线程同步
在多线程环境下,我们需要采取措施来保证多个线程之间的正确互动,从而避免数据竞争和死锁等问题。Java提供了多种机制来协调线程之间的操作,常见的线程同步机制包括:synchronized关键字、Lock接口、volatile关键字等。
synchronized关键字
synchronized关键字可以用来锁定代码块、方法或类。它能够保证同步执行的代码块、方法或者类中的代码,同一时刻只能有一个线程执行。具体方式如下:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public synchronized int getValue() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counter.decrement();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(counter.getValue());
}
}
在上述代码中,我们定义了一个计数器类Counter,并将increment()、decrement()和getValue()方法都标记为同步方法,以实现多个线程对计数器进行安全访问。在main()方法中,我们创建了两个线程,分别调用Counter类的increment()和decrement()方法分别对计数器进行加1和减1操作。最后,我们输出计数器的值。
Lock接口
Lock接口提供了一种更加灵活的线程同步机制。与synchronized关键字不同的是,Lock接口可以使用tryLock()方法来尝试获取锁,而不会阻塞线程。具体实现方式如下:
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public void decrement() {
lock.lock();
try {
count--;
} finally {
lock.unlock();
}
}
public int getValue() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 100000; i++) {
counter.decrement();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(counter.getValue());
}
}
在上述代码中,我们重新实现了计数器的加1和减1操作,并引入了一个Lock接口的实现类ReentrantLock来实现线程同步。在加减法方法中,我们使用lock.lock()方法获取锁,使用try...finally结构保证了无论如何都会释放锁,避免死锁等问题。在getValue()方法中同样利用了Lock机制来保证线程安全。
总结
本文简要介绍了Java多线程的基础知识,包括线程的创建、生命周期、同步等方面,并详细讲解了synchronized和Lock机制在线程同步中的应用。希望通过本文的学习,读者能对Java多线程有更加深入的了解,从而能够更加熟练地利用多线程技术完成复杂的应用程序开发。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java多线程:基础详解 - Python技术站