Java 进阶多线程(一)

简介: Java 进阶多线程

一、多线程

1、继承Thread类(方式一)

1)实现多线程

继承Thread类

重写run()方法

创建线程对象

调用start()方法启动

调用run方法会当成普通方法执行,只有调用start方法才是启动一个新的线程执行

2)优缺点

优点

编码简单

缺点

是单继承,线程类继承Thread后,不能继承其他类,不便于扩展

2、实现Runnable接口(方式二)

1)实现多线程

定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法

创建MyRunnable对象

把MyRunnable任务对象交给Thread线程对象处理

调用线程对象的start()方法启动线程

2)实现多线程(匿名内部类方式)

创建Runnable的匿名内部类对象

交给Thread处理

调用线程对象的start()启动线程

3)优缺点

优点

实现了Runnale接口,可以继续继承和实现

缺点

线程有执行结果是不能直接返回

3、实现Callable、FutureTask接口(方式三)

1)实现多线程

创建Callable接口实现类,重写call()方法,封装

用FutureTask把Callable对象封装成线程任务对象

线程任务对象交给Thread处理,调用start()方法启动线程,执行任务

执行完毕后,通过FutureTask的get方法去获取任务执行的结果

2)优缺点

优点

线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。

可以在线程执行完毕后去获取线程执行的结果。

缺点

编码复杂

方法名 解释

public FutureTask<>(Callable call) 把Callable对象封装成FutureTask对象

public V get() throws Exception 获取线程执行call方法返回的结果

4、Thread线程

1)Thread的构造器

构造器 解释

public Thread(String name) 为当前线程指定名称

public Thread(Runnable target) 封装Runnable对象成为线程对象

public Thread(Runnable target ,String name ) 封装Runnable对象成为线程对象,并指定线程名称

e609cccd993399f78bd2b5ba8e22a1d.png

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("Runnable "+Thread.currentThread().getName()+" ===>> "+i);
        }
    }
}
public class ClassStructure {
    public static void main(String[] args){
        MyRunnable myRunnable = new MyRunnable();
        //分配一个带有指定目标新的线程对象
        Thread thread = new Thread(myRunnable);
        //获取当前线程名称
        String name = thread.getName();
        System.out.println("当前名称-1:"+name);
        //设置新的名称
        thread.setName("Thread-1-新");
        String newName = thread.getName();
        System.out.println("当前名称-1:"+ newName);
        //启动多线程
        thread.start();
        MyRunnable mr = new MyRunnable();
        //分配一个带有指定目标新的线程对象并指定名称
        Thread td = new Thread(mr,"指定名称:");
        String strName = td.getName();
        System.out.println("当前名称-2:"+ strName);
        td.start();
    }
}

5、Thread的方法

1)Thread获取和设置线程名称

方法名 解释

String getName() 获取当前线程的名称,默认线程名称是Thread-索引

void setName(String name) 将此线程的名称更改为指定的名称,通过构造器也可以设置线程名称

0d013aeec7c62cd3ca576069644cda8.png

public class ClassStructure {
    public static void main(String[] args){
        Thread thread = new Thread();
        String name = thread.getName();
        System.out.println(name);
        thread.setName("线程1");
        String nameNew = thread.getName();
        System.out.println(nameNew);
    }
}

2)Thread类获得当前线程的对象

方法名 解释

public static Thread currentThread() 返回对当前正在执行的线程对象的引用

注意:

1、此方法是Thread类的静态方法,可以直接使用Thread类调用。

2、这个方法是在哪个线程执行中调用的,就会得到哪个线程对象。

public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10; i++) {
            //获得当前正在执行的线程对象
            Thread td = Thread.currentThread();
            //获取当前线程名称
            System.out.println(td.getName() + i);
        }
    }
}

3)Thread类的线程休眠方法:

方法名 解释

public static void sleep(long time) 让当前线程休眠指定的时间后再继续执行,单位为毫秒

8d4f641e40c44488e797471899e8f1d.png

public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 10; i++) {
            //获得当前正在执行的线程对象
            Thread td = Thread.currentThread();
            //获取当前线程名称
            System.out.println(td.getName() + i);
        }
    }
}
public class ClassStructure {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable mr = new MyRunnable();
        //分配一个带有指定目标新的线程对象并指定名称
        Thread td = new Thread(mr,"指定名称:");
        String strName = td.getName();
        System.out.println("当前名称-2:"+ strName);
        System.out.println(System.currentTimeMillis());
        //暂停3秒
        Thread.sleep(3000);
        System.out.println(System.currentTimeMillis());
        td.start();
    }
}

二、线程安全

多个线程同时访问同一个共享资源且存在修改该资源

三、线程同步

概念

解决线程安全问题

保证线程安全

多个线程实现先后依次访问共享资源,可以解决安全问题

思想

加锁:让多个线程实现先后依次访问共享资源,可以解决安全问题

1、同步代码块

原理

每次只能一个线程进入,执行完毕后自动解锁,其它线程才可以进来执行

作用

线程安全问题的核心代码给上锁

实现线程安全

对出现问题的核心代码是使用synchronized进行加锁

每次只能一个线程占锁进入执行

格式

synchronized(同步锁对象) {
  操作共享资源的代码(核心代码)
}

同步锁对象要求

对于实例方法建议使用this作为锁对象

对于静态方法建议使用字节码(类名.class)对象作为锁对象

2、同步方法

原理

每次只能一个线程进入,执行完毕后自动解锁,其它线程才可以进来执行

作用

线程安全问题的核心代码给上锁

格式

实现线程安全

对出现问题的核心代码是使用synchronized进行加锁

每次只能一个线程占锁进入执行

修饰符 synchronized 返回值类型 方法名称(形参列表) {
  操作共享资源的代码
}

同步锁对象要求

对于实例方法建议使用this作为锁对象

对于静态方法建议使用字节码(类名.class)对象作为锁对象

底层原理

如果方法是实例方法:同步方法默认用this作为的锁对象。但是代码要高度面向对象

如果方法是静态方法:同步方法默认用类名.class作为的锁对象

3、Lock锁

原理

锁对象Lock,使用更加灵活、方便

Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作

Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来构建Lock锁对象

方法名 解释

public ReentrantLock() 获得Lock锁的实现类对象

void lock() 加锁

void unlock() 解锁


相关文章
|
3天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
40 17
|
14天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
16天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
16天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
16天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
42 3
|
16天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
99 2
|
24天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
47 6
|
1月前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
1月前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
1月前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
53 3