多线程的一些基本知识和坑点

一、理解进程与线程

进程 :是操作系统中资源分配的基本单位,它包含了一个程序的执行实例,是一个动态的概念。
线程 :是进程内的一条执行路径,一个进程可以包含多个线程,各线程共享进程的资源。线程之间可以并发执行,从而实现多任务处理。

二、线程的创建方式

在Java中,我们可以通过以下四种方式进行创建线程:

1. 继承Thread类

java 复制代码
//第一步:自定义线程类继承Thread类,并重写run方法
public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的代码
    }
}
//第二步:创建自定义线程类
MyThread thread = new MyThread();
//第三步:调用start方法
thread.start();

//缺点:OOP单继承局限性

2. 实现Runnable接口

java 复制代码
//第一步:自定义线程类实现Runnable类,并重写run方法
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行的代码
    }
}
//第二步:创建自定义线程类
MyRunnable runnable = new MyRunnable();
//第三步:创建Thread类,把自定义线程类作为参数,传入Thread的构造器中
Thread thread = new Thread(runnable);
//第四步:调用start方法
thread.start();

//优点:避免单继承局限性,灵活方便,更适合用来处理多个线程有共享数据的情况

3. 实现Callable接口

java 复制代码
//第一步:自定义线程类实现Callable接口,并重写call方法
public class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        // 线程执行的代码,并返回结果
        return 42;
    }
}
//第二步:创建自定义线程类
MyCallable callable = new MyCallable();
//第三步:创建执行服务
ExecutorService service = Executors.newSingleThreadExecutor();
//第四步:执行
Future<Integer> future = service.submit(callable);
// 获取线程执行的结果
Integer result = future.get(); 

//优点:call方法可以有返回值,方法可以抛出异常,支持泛型的返回值

4. 使用线程池

咦,这块内容比较多,下次一定哈!!!

三、实践中遇到的坑

1. 多线程注入Spring Bean为空

java 复制代码
//问题代码
public class MyThread extends Thread {

    @Autowired
    private Service service;
    
    @Override
    public void run() {
        // 线程执行的代码
    }
}

原因 :new Thread不在Spring容器中,也就无法获得Spring中的Bean对象
解决:手动注入

java 复制代码
//方法一:通过构造器传入依赖
public class MyThread extends Thread {

    private Service service;

    public MyThread(Service service){
        this.service = service;
    }
    
    @Override
    public void run() {
        // 线程执行的代码
    }
}

//方法二:通过 ApplicationContext 手动获取
@Component
public class BeanContext implements ApplicationContextAware {
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    BeanContext.applicationContext = applicationContext;
  }
  private static ApplicationContext applicationContext;
 
  public static ApplicationContext getApplicationContext(){
    return applicationContext;
  }
}

public class MyThread extends Thread {

    private Service service = BeanContext.getApplicationContext().getBean(Service.class);;
    
    @Override
    public void run() {
        // 线程执行的代码
    }
}

2. 在@Test单元测试中,多线程无法进一步执行

java 复制代码
@Test
public void testThread() {

    MyThread t1 = new MyThread();
    MyThread t2 = new MyThread();
    t1.start();
    t2.start();
}

原因:junit的单元测试方法test是通过TestRunner类执行的,执行的是TestRunner的main方法,最终都会调用 System.exit(),System.exit()是系统调用,作用是通知系统立即结束jvm进程的运行,即使jvm中有线程在运行,jvm也会停止的。

java 复制代码
public static void main(String[] args) {
        TestRunner aTestRunner = new TestRunner();

        try {
            TestResult r = aTestRunner.start(args);
            if (!r.wasSuccessful()) {
                System.exit(1);
            }

            System.exit(0);
        } catch (Exception var3) {
            System.err.println(var3.getMessage());
            System.exit(2);
        }

    }

解决

java 复制代码
//方法一:在main方法里面使用
public static void main(String[] args) {

    MyThread t1 = new MyThread();
    MyThread t2 = new MyThread();
    t1.start();
    t2.start();
    
}
//方法二:使用join方法或者CountDownLatch进行控制
@Test
public void testThread() {

    MyThread t1 = new MyThread();
    MyThread t2 = new MyThread();
    t1.start();
    t2.start();
    t1.join();
    t2.join();
}
相关推荐
kinlon.liu6 分钟前
零信任安全架构--持续验证
java·安全·安全架构·mfa·持续验证
王哲晓27 分钟前
Linux通过yum安装Docker
java·linux·docker
java66666888832 分钟前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言
Violet永存32 分钟前
源码分析:LinkedList
java·开发语言
执键行天涯33 分钟前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
Adolf_19931 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
Jarlen1 小时前
将本地离线Jar包上传到Maven远程私库上,供项目编译使用
java·maven·jar
蓑 羽1 小时前
力扣438 找到字符串中所有字母异位词 Java版本
java·算法·leetcode
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
Reese_Cool1 小时前
【C语言二级考试】循环结构设计
android·java·c语言·开发语言