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() 解锁


相关文章
|
6天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
3天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
16 9
|
6天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
3天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
6天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
15 3
|
4天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
5天前
|
Java
java小知识—进程和线程
进程 进程是程序的一次执行过程,是系统运行的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程 线程,与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比
14 1
|
6天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
6天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
29 1
|
10天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####