线程控制是Java并发编程中的核心内容,涉及到线程的创建、同步、通信、调度等多个方面。
一、线程创建与启动 在Java中,创建线程有两种方式:
继承Thread类和实现Runnable接口。
-
继承Thread类 代码例子:
// 继承Thread类
class MyThread extends Thread {
@Override
public void run() {
// 线程执行体
System.out.println("线程正在执行");
}
}
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread(); // 创建线程对象
myThread.start(); // 启动线程
}
}
-
实现Runnable接口 代码例子:
// 实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行体
System.out.println("线程正在执行");
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable()); // 创建线程对象
thread.start(); // 启动线程
}
}
二、线程同步
当多个线程访问同一资源时,可能会出现线程安全问题。为了解决这个问题,Java提供了同步机制。
-
使用synchronized关键字 代码例子:
class Counter {
private int count = 0;
// 同步方法
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("计数器最终结果:" + counter.getCount());
}
}
-
使用Lock接口 代码例子:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock(); // 加锁
try {
count++;
} finally {
lock.unlock(); // 解锁
}
}
public int getCount() {
return count;
}
}
// 线程控制逻辑与上一个例子类似,此处不再赘述
三、线程通信
线程通信主要涉及到wait()、notify()和notifyAll()这三个方法。 代码例子:
class ProducerConsumer {
private int product = 0;
private boolean isEmpty = true;
public synchronized void produce() {
while (!isEmpty) {
try {
wait(); // 等待消费者消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product++;
System.out.println("生产者生产了产品:" + product);
isEmpty = false;
notifyAll(); // 通知消费者
}
public synchronized void consume() {
while (isEmpty) {
try {
wait(); // 等待生产者生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费了产品:" + product);
isEmpty = true;
notifyAll(); // 通知生产者
}
}
public class Main {
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
pc.produce();
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
pc.consume();
}
});
producer.start();
consumer.start();
}
}
四、线程调度
Java提供了线程调度器来控制线程的执行顺序。
-
设置线程优先级 代码例子:
Thread t1 = new Thread(() -> {
// 线程执行体
});
t1.setPriority(Thread.MAX_PRIORITY); // 设置线程优先级为最高
Thread t2 = new Thread(() -> {
// 线程执行体
});
t2.setPriority(Thread.MIN_PRIORITY); // 设置线程优先级为最低
t1.start();
t2.start();
-
使用线程池 线程池可以有效地管理和控制线程的创建和销毁,提高系统性能。 代码例子:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
// 创建固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
// 线程执行体
System.out.println("线程池中的线程正在执行:" + Thread.currentThread().getName());
});
}
// 关闭线程池
executorService.shutdown();
}
}
五、线程中断
线程中断是一种协作机制,用于通知线程中断其正在执行的任务。 代码例子:
class MyRunnable implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 执行任务
System.out.println("线程正在执行任务");
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {
// 捕获中断异常,并设置中断标志
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
System.out.println("线程被中断,退出任务");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new MyRunnable());
thread.start();
// 主线程休眠一段时间后中断子线程
Thread.sleep(3000);
thread.interrupt();
}
}
六、线程局部变量
ThreadLocal类可以创建线程局部变量,确保每个线程都有自己独立的变量副本。
代码例子:
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
// 创建线程局部变量
private static final ThreadLocal<Integer> threadLocalValue = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return new AtomicInteger().incrementAndGet();
}
};
public static void main(String[] args) {
// 在不同线程中访问线程局部变量
Thread t1 = new Thread(() -> {
System.out.println("线程1的局部变量值:" + threadLocalValue.get());
});
Thread t2 = new Thread(() -> {
System.out.println("线程2的局部变量值:" + threadLocalValue.get());
});
t1.start();
t2.start();
}
}
七、总结
通过这些机制,我们可以更好地管理和控制线程的执行,编写出高效、稳定的并发程序。