Java多线程的基础知识
在 Java 编程中,多线程是非常常见的技术,多线程的使用可以在提高程序并发性能的同时,也增加了程序的复杂度,因此学好多线程技术对于 Java 开发人员来说是非常重要的。
1. 创建线程
在 Java 中创建一个线程有两种主要方法:
1.1. 实现 Runnable 接口
Runnable 接口是 Java 多线程中的一个基本接口,通过实现 Runnable 接口并覆盖 run
方法实现多线程。
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("当前线程名: " + Thread.currentThread().getName());
}
}
然后,可以通过创建 Thread 对象并将其作为 Runnable 对象传递来创建线程。
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable, "线程1");
thread.start();
1.2. 继承 Thread 类
继承 Thread 类是创建线程的另外一种方式,通过覆盖 run
方法实现多线程。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("当前线程名: " + Thread.currentThread().getName());
}
}
然后,可以直接创建 MyThread 的实例,并调用 start
方法来创建线程。
MyThread myThread = new MyThread();
myThread.setName("线程2");
myThread.start();
2. 线程同步
在多线程编程中,线程同步是一个非常关键的问题。当多个线程共享资源时,需要确保每个线程在访问共享资源时不会相互干扰。
2.1. 使用 synchronized 关键字
synchronized
关键字被用于控制并发访问临界区,只有获得了该锁的线程才可以进入临界区,其他线程需要等待锁的释放。
public class Counter {
private int count;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
count--;
}
public int getCount() {
return count;
}
}
2.2. 使用 Lock 接口
Lock
接口是 synchronized
关键字的替代品,它拥有更多的新增特性,能够提供更好的性能和可扩展性。
public class Counter {
private int count;
private final 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 getCount() {
return count;
}
}
3. 示例说明
示例一
假设我们需要统计一个整数数组中所有元素的和,可以将数组分成若干个小块,然后每个线程负责计算每个小块的和,并将结果汇总起来。
public class ParallelSum {
public static void main(String[] args) throws InterruptedException {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numOfThreads = 3;
ExecutorService executor = Executors.newFixedThreadPool(numOfThreads);
List<Future<Integer>> list = new ArrayList<>();
int chunkSize = nums.length / numOfThreads;
for (int i = 0; i < nums.length; i += chunkSize) {
int end = Math.min(nums.length, i+chunkSize);
int[] part = Arrays.copyOfRange(nums, i, end);
Callable<Integer> callable = new SumTask(part);
Future<Integer> future = executor.submit(callable);
list.add(future);
}
int totalSum = 0;
for (Future<Integer> future : list) {
totalSum += future.get();
}
executor.shutdown();
System.out.println(totalSum);
}
static class SumTask implements Callable<Integer> {
private int[] nums;
public SumTask(int[] nums) {
this.nums = nums;
}
@Override
public Integer call() {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
}
}
}
示例二
在下面的代码中,Task 类是一个在循环中执行 5 次以输出当前线程名的任务。使用线程池创建了 10 个线程 ThreadPoolExecutor,每个线程都将执行这个任务。
public class MultiThreading {
public static void main(String[] args) {
Runnable runnableTask = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("线程名: " + Thread.currentThread().getName());
}
};
ExecutorService executor = new ThreadPoolExecutor(
5, //核心线程数
10, //最大线程数
1, //线程空闲时间
TimeUnit.SECONDS, //时间单位
new LinkedBlockingQueue<>() //任务队列
);
for (int i = 0; i < 10; i++) {
executor.execute(runnableTask);
}
executor.shutdown();
}
}
4. 小结
本文简要介绍了 Java 多线程的基础知识和线程同步问题,同时还给出了两个示例说明。多线程编程是 Java 编程中不可避免的一部分,通过本文的学习,相信读者已经对 Java 多线程有了深入的了解和实战经验。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java基础之多线程 - Python技术站