彻底搞懂Java多线程(一)

彻底搞懂Java多线程(一)

为什么需要多线程

在Java应用程序中,多线程可以帮助我们利用CPU资源,提高程序的执行效率,加速程序的运行速度。理论上,一个程序的执行速度可以比单线程的程序快1到100倍不等。

Java多线程的实现方式

Java多线程的实现方式主要有两种:继承Thread类和实现Runnable接口。

继承Thread类

使用继承Thread类的方式,需要重写Thread类的run()方法,并在该方法中实现多线程的操作。

public class MyThread extends Thread {
    // 重写run方法
    public void run() {
        // 多线程的操作
    }
}

实现Runnable接口

使用实现Runnable接口的方式,需要在类中实现Runnable接口的run()方法,并在该方法中实现多线程的操作。然后,创建Thread类的实例,将Runnable对象作为它的构造函数参数传递,最后调用start()方法启动线程。

public class MyRunnable implements Runnable {
    // 实现run方法
    public void run() {
        // 多线程的操作
    }
}

public class Test {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

Java多线程的生命周期

Java多线程的生命周期包括5个状态:新建、就绪、运行、阻塞和死亡。

新建状态

当用new关键字创建一个Thread对象时,线程进入新建状态。

就绪状态

当线程调用start()方法时,线程进入就绪状态,等待JVM调度执行。

运行状态

当线程被JVM调度执行时,线程进入运行状态。

阻塞状态

当线程在等待一个监视器锁或某些操作执行的结果时,线程进入阻塞状态。

死亡状态

当线程执行完run()方法后或因异常而结束时,线程进入死亡状态。

Java多线程的同步机制

在Java多线程环境中,同步机制是用来解决多个线程访问共享资源的问题。

synchronized关键字

synchronized关键字可以用来确保同一时间只有一个线程能够访问共享资源。

public class Test {
    // 定义共享变量count
    private static int count = 0;
    // 在方法中使用synchronized关键字同步访问count变量
    public synchronized static void add() {
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        // 创建20个线程
        for (int i = 0; i < 20; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 每个线程循环调用1000次add方法
                    for (int i = 0; i < 1000; i++) {
                        add();
                    }
                }
            });
            thread.start();
        }
        // 等待所有线程执行完毕
        Thread.sleep(1000);
        System.out.println(count);
    }
}

wait()和notify()方法

wait()和notify()方法是Java中用于线程同步的另外两个重要的方法。

  • wait()方法会让当前的线程进入等待状态,直到其它线程调用notify()方法将其唤醒。
  • notify()方法会唤醒处于等待状态的线程,但不会释放锁,因此必须等到执行notify()方法的线程释放锁之后其他线程才能继续执行。
public class Test {
    public static void main(String[] args) throws InterruptedException {
        final Object lock = new Object();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("Thread1等待...");
                        lock.wait();
                        System.out.println("Thread1被唤醒!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("Thread2睡眠1秒钟...");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.notify();
                }
            }
        });
        thread1.start();
        thread2.start();
    }
}

示例说明

示例1

这是一个简单的多线程示例,创建了20个线程,每个线程循环调用1000次add方法,将一个静态变量count的值加1。

public class Test {
    // 定义共享变量count
    private static int count = 0;
    // 在方法中使用synchronized关键字同步访问count变量
    public synchronized static void add() {
        count++;
    }
    public static void main(String[] args) throws InterruptedException {
        // 创建20个线程
        for (int i = 0; i < 20; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 每个线程循环调用1000次add方法
                    for (int i = 0; i < 1000; i++) {
                        add();
                    }
                }
            });
            thread.start();
        }
        // 等待所有线程执行完毕
        Thread.sleep(1000);
        System.out.println(count);
    }
}

示例2

这个示例展示了wait()和notify()方法的使用。在线程1调用lock.wait()方法进入等待状态后,线程2睡眠1秒钟,然后调用lock.notify()方法唤醒在线程1中等待的线程。

public class Test {
    public static void main(String[] args) throws InterruptedException {
        final Object lock = new Object();
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("Thread1等待...");
                        lock.wait();
                        System.out.println("Thread1被唤醒!");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        System.out.println("Thread2睡眠1秒钟...");
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.notify();
                }
            }
        });
        thread1.start();
        thread2.start();
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:彻底搞懂Java多线程(一) - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • php使用curl并发减少后端访问时间的方法分析

    PHP使用cURL并发技术实现优化后端访问时间 在高并发的web应用中,后端向多个不同的目标执行HTTP请求是很常见的,并发执行这些请求是可以显著提高应用性能的。cURL库是PHP中强大而常用的HTTP客户端库之一,本文将介绍如何使用cURL的并发技术来减少后端访问时间。 什么是cURL并发技术? cURL并发技术是一种将多个HTTP请求同时发送到后端,并在…

    多线程 2023年5月16日
    00
  • C#多线程系列之线程通知

    C#多线程系列之线程通知主要涵盖三个部分:Monitor、AutoResetEvent和ManualResetEvent。 Monitor 在C#中,Monitor类是一种基本的同步机制,支持两种操作:Enter()和Exit()。Enter()用于请求获取对象的锁,而Exit()用于释放对象的锁,最终达到线程同步的目的。 Monitor类的典型应用场景是在…

    多线程 2023年5月17日
    00
  • 如何用PHP实现多线程编程

    创建多线程程序可以增加应用程序的效率,对于 PHP 程序员来说,也要掌握多线程编程技术。 实现 PHP 多线程编程的方式有很多,比如使用 pthreads 扩展、使用 pcntl 扩展、使用多进程(fork)等。下面我们举两个例子分别介绍使用 pthreads 扩展和多进程实现多线程编程的方法。 使用 pthreads 扩展 pthreads 扩展是一个多线…

    多线程 2023年5月17日
    00
  • .net中线程同步的典型场景和问题剖析

    针对“.net中线程同步的典型场景和问题剖析”的话题,我来进行详细讲解,包括以下几个部分: 线程同步的概念 线程同步的必要性和作用 线程同步的实现方式 .net中线程同步的典型场景和问题剖析 示例说明 1. 线程同步的概念 线程同步是指在多个线程之间,对共享资源的访问进行协调和管理,以避免竞争条件和死锁等问题。 2. 线程同步的必要性和作用 当多个线程同时访…

    多线程 2023年5月16日
    00
  • Spring Boot中配置定时任务、线程池与多线程池执行的方法

    下面是Spring Boot中配置定时任务、线程池与多线程池执行的完整攻略: 定时任务 配置定时任务 使用Spring Boot配置定时任务十分方便,只需要使用 @Scheduled 注解即可。 @Component public class MyTask { @Scheduled(fixedDelay = 5000) //间隔5秒执行 public voi…

    多线程 2023年5月16日
    00
  • Java并发编程深入理解之Synchronized的使用及底层原理详解 上

    Java并发编程深入理解之Synchronized的使用及底层原理详解 Synchronized的基本使用 Synchronized是Java中用于实现线程同步的基本方法之一,其使用方式为在方法或代码块前加上synchronized关键词。 public synchronized void method() { // method body } synchr…

    多线程 2023年5月17日
    00
  • Go语言并发之原子操作详解

    《Go语言并发之原子操作详解》是一篇介绍Go语言中原子操作的高质量文章,下面就该主题进行详细的讲解及其示例说明。 什么是原子操作 原子操作是指一个操作是不可分割的一整个事务。当我们在运行并发程序的时候,原子操作就能够防止竞争条件的发生,保证数据的一致性以及避免数据竞争。 Go语言中的原子操作 Go语言内置了原子操作,可以通过原子操作实现并发安全。在Go语言中…

    多线程 2023年5月17日
    00
  • Java并发编程变量可见性避免指令重排使用详解

    Java并发编程变量可见性避免指令重排使用详解 什么是Java并发编程的变量可见性 Java并发编程中典型问题之一是变量可见性。在多线程环境下,一个线程修改的变量不一定会立即对另一个线程可见。这是因为每个线程都有它自己的工作内存,并且线程之间不一定立即同步。 例如,当一个线程修改了变量X的值,如果该变量在另一个线程中被使用,那么第二个线程可能会看到第一个线程…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部