目录
一、什么是多线程?
线程是程序执行的基本单位,一个程序至少有一个进程,而一个进程至少包含一个线程。多线程技术是指在一个程序中同时运行多个线程,每个线程可以执行不同的任务,从而提高程序的执行效率。
代码示例
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
以上代码中,main
方法本身就是一个线程。当我们启动程序时,它就是一个单线程程序(day11、多线程内容)。
二、多线程的创建方式
-
继承Thread类
通过继承
java.lang.Thread
类来创建一个线程,重写run()
方法,然后调用start()
方法启动线程。
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
-
优点是实现简单,缺点是由于Java不支持多继承,继承
Thread
类后无法继承其他类(day11、多线程内容)。 -
实现Runnable接口
定义一个类实现
Runnable
接口,重写run()
方法,通过Thread
类创建线程对象并启动。 -
class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + ": " + i); } } } public class RunnableDemo { public static void main(String[] args) { MyRunnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start(); } }
-
此方式具有更好的扩展性,因为任务类可以继承其他类(day11、多线程内容)。
-
实现Callable接口
Callable
接口是Java 5引入的新特性,它可以返回执行结果,并抛出异常。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
}
public class CallableDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> result = executor.submit(new MyCallable());
try {
System.out.println("Sum: " + result.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
-
使用
Callable
和Future
可以获得线程的执行结果(day11、多线程内容)。
三、线程同步与安全
当多个线程同时访问同一资源时,可能会引发线程安全问题,例如数据不一致等。Java提供了多种方式来实现线程同步,确保线程安全。
-
同步代码块
synchronized (锁对象) {
// 需要同步的代码
}
-
使用同步代码块可以确保同一时间只有一个线程访问同步代码,从而保证数据的一致性。
-
同步方法
直接在方法上加
synchronized
关键字,适用于需要完整同步的方法。 -
public synchronized void method() { // 需要同步的方法 }
-
同步方法与同步代码块的区别在于前者锁定整个方法,后者只锁定某段代码(day11、多线程内容)(day11、多线程内容)。
-
使用Lock对象
JDK 5引入了
java.util.concurrent.locks.Lock
接口,它提供了更灵活的锁机制。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Lock lock = new ReentrantLock();
lock.lock();
try {
// 需要同步的代码
} finally {
lock.unlock();
}
-
Lock
相比synchronized
更加灵活且具有更好的性能(day11、多线程内容)。
四、线程池
线程池是一种线程管理机制,通过预先创建的线程来处理任务,避免频繁创建和销毁线程所带来的性能开销。
-
创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executorService.submit(new MyRunnable());
}
executorService.shutdown();
通过Executors
工具类提供的方法可以方便地创建各种类型的线程池,例如固定大小线程池、缓存线程池、单线程池等
结论
多线程技术为我们提供了有效的并发处理能力,能够显著提高程序的执行效率。通过正确的使用多线程技术和相应的同步机制,可以有效避免线程安全问题,充分发挥多线程的优势。在实际应用中,根据具体的需求选择合适的线程创建方式和同步策略是至关重要的