一个进程指的是一个正在执行的应用程序,线程的功能就是执行应用程序中的某个具体任务。
线程与进程的关系
线程和进程之间的关系,类似于工厂和工人之间的关系,进程好比是工厂,线程就如同工厂中的工人。一个进程至少包含 1 个线程,可以包含多个线程,所有线程共享进程的资源,各个线程也可以拥有属于自己的私有资源。
什么是多线程
所谓多线程,即一个进程中拥有多(≥2)个线程,线程之间相互协作、共同执行一个应用程序。
当进程中仅包含 1 个执行程序指令的线程时,该线程又称“主线程”,这样的进程称为“单线程进程”。
如何创建一个多线程
继承Thread类,重写run()方法
public class Text1 extends Thread{
@Override
public void run() {
// 在这里编写线程要执行的操作
System.out.println("线程开始执行");
// 执行其他操作...
System.out.println("线程执行完毕");
}
public static void main(String[] args) {
// 创建自定义线程的实例
Text1 myThread = new Text1();
// 启动线程
myThread.start();
try {
// 等待线程执行完毕
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完毕");
}
}
Spring实现多线程
- 配置异步支持:
在Spring配置文件中启用异步支持。对于基于XML的配置,您可以添加以下内容:
<task:annotation-driven executor="myExecutor" /> <task:executor id="myExecutor" pool-size="10" />
对于基于注解的配置,可以在配置类上添加
@EnableAsync
注解。 - 创建异步方法:在Spring管理的Bean中创建异步方法,并使用
@Async
注解标记这些方法。@Service public class MyService { @Async public void asyncMethod() { // 在这里编写异步方法的操作 System.out.println("异步方法开始执行"); System.out.println("异步方法执行完毕"); } }
- 调用异步方法
@Component public class MyComponent { @Autowired private MyService myService; public void doSomething() { // 调用异步方法 myService.asyncMethod(); } }
synchronized锁的实现
锁是一种同步机制,用于在多线程环境中控制对共享资源的访问。它确保同一时间只有一个线程可以执行被锁保护的代码块或方法,从而避免多个线程同时访问和修改共享资源导致的数据竞争和不一致性。
在Java中,synchronized
关键字可以用来创建锁,它可以应用于方法或代码块。当一个线程获得锁时,其他线程将被阻塞,直到该线程释放锁。
锁的概念有以下几个关键点:
-
互斥性(Mutual Exclusion):同一时间只能有一个线程持有锁,其他线程必须等待锁的释放才能获得访问权限。这确保了对共享资源的独占性访问。
-
可见性(Visibility):当一个线程释放锁时,它将所做的修改刷新到主内存,并使得其他线程能够看到最新的值。这确保了共享资源的可见性,避免了数据不一致的问题。
-
顺序性(Ordering):锁可以确保被锁保护的代码块或方法按照一定的顺序执行。即使有多个线程同时请求锁,只有一个线程能够成功获取锁并执行,其他线程将按照请求的顺序等待。
使用锁的目的是保护共享资源,防止多个线程同时对其进行读写操作,从而避免数据的破坏或不一致。锁的正确使用可以确保线程安全,避免竞态条件和其他并发问题。然而过度的使用锁,可能会导致性能问题,因为它会限制并发性。
- 同步方法:
public class MyLock { public synchronized void synchronizedMethod() { } }
将方法声明为
synchronized
,这意味着在任何时候只有一个线程可以执行该方法。当一个线程进入同步方法时,它将获得当前对象的锁,其他线程将被阻塞,直到该线程执行完毕并释放锁。 - 同步代码块:
首先,声明了一个
lockObject
对象,用于实现同步。这个对象将用作锁,在同步代码块中获取锁的时候使用。然后,在
someMethod()
方法中,包含了同步代码块。这个同步代码块使用synchronized
关键字,并传入lockObject
对象作为锁。当一个线程执行到同步代码块时,它会尝试获取
lockObject
对象的锁。如果没有其他线程持有该锁,那么该线程将获得锁,并执行同步代码块中的代码。在同步代码块中,您可以编写需要同步的操作,以确保线程安全。其他线程在同一时间只有一个能够成功获取到
lockObject
对象的锁,其他线程将被阻塞,直到持有锁的线程执行完同步代码块并释放锁。这样可以确保在同一时间只有一个线程能够执行同步代码块中的代码,避免了对共享资源的并发访问问题。在同步代码块之外的其他代码是非同步代码,它们不受锁的影响,可以在没有锁的情况下并发执行。
通过这种方式,使用
synchronized
关键字和一个对象锁,可以实现简单的锁机制,确保对共享资源的访问是线程安全的。public class MyLock { private final Object lockObject = new Object(); public void someMethod() { // 其他非同步代码... synchronized (lockObject) { // 在这里编写需要同步的代码 // 这个同步块将获取lockObject对象的锁 } // 其他非同步代码... } }