详谈Java多线程的几个常用关键字

yizhihongxing

接下来我将详细讲解“详谈Java多线程的几个常用关键字”。

一、Java多线程的几个常用关键字

Java中的多线程是通过Thread类及Runnable接口来实现的。在Java多线程中,有几个常用关键字需要熟知,如下所示:

  1. synchronized:用于实现同步,防止并发访问共享数据发生错误,并且保证了多线程的协调运行。

  2. volatile:用于保证可见性和禁止指令重排。

  3. waitnotifynotifyAll:用于实现线程之间的协作。

下面我们详细介绍一下这几个关键字及其使用场景。

二、synchronized关键字

synchronized关键字是Java中实现同步的一种方式。它可以修饰方法或代码块,在多线程中保证线程之间的同步执行,从而防止数据的竞争和错误。

1. synchronized方法

在Java中,使用synchronized关键字修饰的方法称为synchronized方法。当某个线程调用一个synchronized方法时,会自动获取该对象的锁,直到该方法执行完毕后才会自动释放该对象锁。

示例代码:

public class SynchronizedDemo {
    public synchronized void synchronizedMethod() {
        // do something...
    }
}

上面的示例中,我们使用synchronized关键字修饰了synchronizedMethod方法,从而保证该方法在多线程执行时的同步访问。

2. synchronized代码块

synchronized关键字还可以用于修饰代码块,使用synchronized代码块可以精确控制多个线程之间的同步访问。

示例代码:

public class SynchronizedDemo {
    public void synchronizedBlock() {
        synchronized (this) {
            // do something...
        }
    }
}

上面的示例中,我们使用synchronized关键字修饰了代码块,从而控制某段代码在多线程间的同步访问。

三、volatile关键字

volatile关键字与synchronized关键字一样,都是为了多线程的正确执行而设计的。使用volatile关键字可以保证可见性和禁止指令重排。

1. 保证可见性

Java内存模型中的可见性是指,当一个线程修改了共享变量的值时,其他线程能够立即看到修改后的值。使用volatile关键字修饰的变量,可以使该变量的修改对其他线程立即可见。

示例代码:

public class VolatileDemo {
    private volatile int value = 0;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        VolatileDemo demo = new VolatileDemo();

        new Thread(() -> {
            demo.setValue(10);
        }).start();

        new Thread(() -> {
            System.out.println(demo.getValue());
        }).start();
    }
}

上面的示例中,我们使用volatile关键字修饰了value变量,从而实现了多个线程之间的可见性。

2. 禁止指令重排

在Java编译器中,为了优化代码运行速度,可能会进行指令重排,即改变指令的顺序,但并不会改变程序的运行结果。但在多线程中,指令重排会导致程序出现难以预料的错误。因此,为了保证多线程执行的正确性,我们需要使用volatile关键字来禁止指令重排。

示例代码:

public class VolatileDemo {
    private static volatile VolatileDemo instance;

    public static VolatileDemo getInstance() {
        if (instance == null) {
            synchronized (VolatileDemo.class) {
                if (instance == null) {
                    instance = new VolatileDemo();
                }
            }
        }
        return instance;
    }
}

上面的示例中,我们使用了volatile关键字来修饰单例模式中的instance变量,从而保证了该变量的可见性和禁止指令重排。

四、wait、notify、notifyAll关键字

在Java中,我们可以使用waitnotifynotifyAll关键字来实现线程间的协作,从而更好地实现多线程的协调运行。

1. wait关键字

wait关键字用于使当前线程等待,直到其他线程调用该对象的notifynotifyAll方法,唤醒当前线程继续执行。

示例代码:

public class WaitNotifyDemo {
    private boolean flag = true;

    public synchronized void printA() {
        while (!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("A");
        flag = false;
        notifyAll();
    }

    public synchronized void printB() {
        while (flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("B");
        flag = true;
        notifyAll();
    }

    public static void main(String[] args) {
        WaitNotifyDemo demo = new WaitNotifyDemo();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.printA();
            }
        }).start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                demo.printB();
            }
        }).start();
    }
}

上面的示例中,我们使用了waitnotifyAll关键字来实现了线程之间的协作,当打印完"A"后,会唤醒其他线程去执行。

2. notify关键字

notify关键字唤醒一个正在等待当前对象锁的线程。如果有多个线程正在等待该对象锁,则只有一个线程会被唤醒。

示例代码:

public class WaitNotifyDemo {
    private Object lock = new Object();

    public void print() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " 获取到锁");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.notify();
            System.out.println(Thread.currentThread().getName() + " 唤醒等待线程");
        }
    }

    public static void main(String[] args) {
        WaitNotifyDemo demo = new WaitNotifyDemo();

        new Thread(() -> {
            synchronized (demo.lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 等待获取锁");
                    demo.lock.wait();
                    System.out.println(Thread.currentThread().getName() + " 获取到锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            demo.print();
        }).start();
    }
}

上面的示例中,我们使用了waitnotify关键字来实现了线程之间的协作,当线程1等待获取锁时,线程2获取到锁并执行完毕,然后唤醒线程1继续执行。

3. notifyAll关键字

notifyAll关键字唤醒所有正在等待当前对象锁的线程,让它们去竞争获取对象锁。

示例代码:

public class WaitNotifyDemo {
    private Object lock = new Object();

    public void print() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " 获取到锁");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.notifyAll();
            System.out.println(Thread.currentThread().getName() + " 唤醒等待线程");
        }
    }

    public static void main(String[] args) {
        WaitNotifyDemo demo = new WaitNotifyDemo();

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                synchronized (demo.lock) {
                    try {
                        System.out.println(Thread.currentThread().getName() + " 等待获取锁");
                        demo.lock.wait();
                        System.out.println(Thread.currentThread().getName() + " 获取到锁");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        new Thread(() -> {
            demo.print();
        }).start();
    }
}

上面的示例中,我们使用了waitnotifyAll关键字来实现了线程之间的协作,当线程1等待获取锁时,线程2获取到锁并执行完毕,然后唤醒所有等待线程去竞争获取对象锁。

五、总结

Java中的多线程是一种非常重要的技术,其中有几个常用关键字需要熟知,如synchronizedvolatilewaitnotifynotifyAll等。使用这些关键字可以使多线程之间的协调运行更加平稳和有效。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详谈Java多线程的几个常用关键字 - Python技术站

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

相关文章

  • Java 详解循环屏障CyclicBarrier如何实现多线程分段等待执行完成

    让我来详细给你讲解一下“Java 详解循环屏障CyclicBarrier如何实现多线程分段等待执行完成”的攻略。 CyclicBarrier 是什么? 在 Java 语言中,CyclicBarrier 是一个同步辅助类,能够让一组线程同时到达一个屏障(也称栅栏)位置,然后再一起继续执行。其实,CyclicBarrier 就是一个字面意义的循环屏障。 如何使用…

    多线程 2023年5月16日
    00
  • 剖析Fork join并发框架工作窃取算法

    剖析Fork/Join并发框架工作窃取算法 什么是Fork/Join并发框架 Fork/Join并发框架是Java SE 7加入的一个用于并行执行任务的框架。这个框架的核心思想是:将一个大的任务拆分成若干个小任务分别执行,最后将执行结果汇总。 工作窃取算法 工作窃取算法(Work Stealing Algorithm)是Fork/Join并发框架中实现任务调…

    多线程 2023年5月17日
    00
  • Java多线程 线程状态原理详解

    Java多线程 线程状态原理详解 介绍 Java中的线程可以并行执行多个代码块,既可提高程序执行效率,又可防止程序因某些阻塞造成“卡死”。 线程状态就是指线程在代码执行期间所处的不同运行状态,进而影响着线程的执行顺序及资源分配。在Java中,线程状态主要由以下5种状态组成: 新建状态(New) 就绪状态(Runnable) 阻塞状态(Blocked) 等待状…

    多线程 2023年5月17日
    00
  • 高并发系统数据幂等的解决方案

    高并发系统数据幂等是保证系统在并发请求中数据的正确性和一致性的关键问题之一。以下是一些常见的解决方案: 1. 通过唯一索引去重 在实现数据幂等性时,可以将唯一索引作为去重的依据。具体操作是,首先在数据库中创建指定字段的唯一索引,并在系统中将该索引作为去重主键。当系统接收到请求时,先在唯一索引字段上进行查询,如果数据库中已存在该数据,则直接返回相应的数据;反之…

    多线程 2023年5月16日
    00
  • 异步http listener 完全并发处理惩罚http恳求的小例子

    为了详细讲解“异步http listener 完全并发处理惩罚http恳求的小例子”的完整攻略,我将分以下几个部分逐一介绍: 什么是异步http listener? 异步http listener是指在ASP.NET Core中,使用async/await语法和IHostedService接口实现的一个异步http服务。它支持同时处理多个http请求,并能够…

    多线程 2023年5月16日
    00
  • 利用redis实现分布式锁,快速解决高并发时的线程安全问题

    利用Redis实现分布式锁是一种常见的解决高并发时线程安全问题的方式。在使用Redis实现分布式锁之前,需要针对具体需求选择使用哪种方式。 一、获取分布式锁的Demo 准备Redis连接客户端:我们可以使用Jedis或Lettuce等第三方开源Redis客户端,将其引入到项目中。 连接Redis服务:使用该客户端连接我们的Redis服务,用于后续的操作。 J…

    多线程 2023年5月16日
    00
  • java多线程之并发工具类CountDownLatch,CyclicBarrier和Semaphore

    Java多线程之并发工具类 在Java多线程编程中,有一些并发控制的工具类可以帮助我们实现更好的程序并发控制,其中比较常用的有三个类:CountDownLatch、CyclicBarrier和Semaphore。 CountDownLatch CountDownLatch是一种同步工具类,它允许一个线程等待多个线程完成操作。初始化时需要指定要等待的线程数量,…

    多线程 2023年5月16日
    00
  • Java面试题冲刺第十二天–数据库(2)

    来给大家详细讲解一下“Java面试题冲刺第十二天–数据库(2)”的完整攻略。 一、数据库相关知识点 本篇文章主要涉及以下数据库相关知识点: 数据库事务 数据库锁 事务的隔离级别 数据库优化 二、数据库事务 数据库事务可以保证多个对数据库的操作是一个原子性操作,即只要其中有一个操作失败,整个事务都将回滚。 在Java中使用JDBC进行事务控制时,需要使用以下…

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