浅谈Java多线程实现及同步互斥通讯

浅谈Java多线程实现及同步互斥通讯

引言

多线程是指一种多个线程执行完毕后可以得到更好的系统性能的机制。Java多线程的实现是通过创建Thread实例或者继承Thread类并重写它的run()方法来完成的。Java也提供了一个Java.util.concurrent包,它为Java多线程编程提供了更多的助力。在多线程编程中,同步互斥是一种非常重要的问题,它可以确保多个线程协同工作时不会出现死锁、竞态条件和其它不安全的情况。

Java多线程实现

通过继承Thread类实现

下面这个例子演示了如何通过继承Thread类来实现多线程。

class MyThread extends Thread {
    @Override
    public void run() {
        // 这里可以放置线程的任务代码
    }
}

public class TestMyThread {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}

通过运行TestMyThread类,该程序会创建一个新的线程并开始运行。

通过Runnable接口实现

下面这个例子演示了如何通过实现Runnable接口来实现多线程。

class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 这里可以放置线程的任务代码
    }
}

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

通过运行TestMyRunnable类,该程序会创建一个新的线程并开始运行。

同步互斥

当多个线程访问共享资源时,就有可能会出现多个线程访问同一资源的情况,这时就需要同步互斥来保护共享资源。Java提供了两种方法来实现同步互斥:synchronized关键字和Lock接口。

synchronized关键字

我们可以使用synchronized关键字来保护代码块或者方法,使得多个线程必须获得锁才能执行这个代码块或方法。下面是一个使用synchronized关键字的例子。

class Counter {
    private int count = 0;
    public synchronized void increment() {
        count++;
    }
    public synchronized void decrement() {
        count--;
    }
    public synchronized int getCount() {
        return count;
    }
}

public class TestCounter {
    public static void main(String[] args) {
        Counter counter = new Counter();
        // 创建多线程对计数器进行操作
    }
}

上面的代码创建了一个计数器类,接着我们在Counter类的increment()、decrement()和getCount()方法上都加上了synchronized关键字。这样就可以保证在多个线程同时访问这些方法时,只有一个线程可以获得锁并执行方法,其它线程则必须等待。

Lock接口

另外一种实现同步互斥的方式是使用Lock接口。与synchronized关键字不同的是,Lock接口使用时需要程序员主动获取锁和释放锁。下面是一个使用Lock接口的例子。

class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    public void decrement() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }
    public int getCount() {
        return count;
    }
}

public class TestCounter {
    public static void main(String[] args) {
        Counter counter = new Counter();
        // 创建多线程对计数器进行操作
    }
}

上面的代码创建了一个计数器类,接着我们在Counter类中添加了一个Lock接口类型的成员变量lock。然后在increment()、decrement()方法中使用lock.lock()获取锁,并在finally块中使用lock.unlock()释放锁。这样就可以保证每个线程进入这个方法时必须先获得锁,如果没有得到锁则线程进入等待状态。

示例

示例1:线程安全的懒汉式单例模式

public class Singleton {
    private static Singleton instance;
    private static Lock lock = new ReentrantLock();
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            lock.lock();
            try {
                if (instance == null) {
                    instance = new Singleton();
                }
            } finally {
                lock.unlock();
            }
        }
        return instance;
    }
}

上面的代码实现了一个线程安全的懒汉式单例模式。在getInstance()方法中我们使用了Lock接口来实现同步互斥,确保在多个线程同时获取单例对象时不会出现问题。

示例2:多线程实现带判断Condition的生产者消费者模式

public class ProduceConsume {
    private LinkedList<Integer> list = new LinkedList<>();
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();
    private final int MAXSIZE = 5;
    public void produce() {
        lock.lock();
        try {
            while (list.size() == MAXSIZE) {
                notFull.await();
            }
            int num = new Random().nextInt(10);
            list.add(num);
            System.out.println("生产者生产了" + num);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void consume() {
        lock.lock();
        try {
            while (list.size() == 0) {
                notEmpty.await();
            }
            int num = list.removeFirst();
            System.out.println("消费者消费了" + num);
            notFull.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

上面的代码实现了一个带判断Condition的生产者消费者模式。使用Lock接口的实例的Condition对象,使生产者要在容器满的时候停止生产,并等待消费者来消费;消费者要在容器空的时候停止消费,并等待生产者来生产。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Java多线程实现及同步互斥通讯 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C# Linq的OrderBy()方法 – 根据指定的键按升序对序列的元素进行排序

    C#中的Linq提供了一种方便的方法来处理数据序列,其中OrderBy()是排序操作中的一个重要部分。OrderBy()方法可以按照序列中指定的键值对序列进行排序,并返回一个IEnumerable类型的序列。 语法格式 public static IOrderedEnumerable<TSource> OrderBy<TSource, TK…

    C# 2023年4月19日
    00
  • 使用.net core3.0 正式版创建Winform程序的方法(图文)

    下面是详细的攻略: 确保环境 在开始创建Winform程序之前,需要先确保本地计算机上已经安装了.net core3.0正式版本。如果尚未安装,请先访问Microsoft官网下载安装包并完成安装。为确保已经安装成功,请在控制台中输入以下命令: dotnet –version 如果程序返回了版本号,表示已经安装成功。 创建Winform应用程序 接下来,可以…

    C# 2023年6月3日
    00
  • C# Directory.CreateDirectory – 创建目录

    Directory.CreateDirectory 方法的作用和使用方法 Directory.CreateDirectory 方法概述 Directory.CreateDirectory 方法用于创建指定路径下的所有目录。如果要创建一个新的目录,需要使用该方法。Directory.CreateDirectory 方法是 System.IO 命名空间的静态方法…

    C# 2023年4月19日
    00
  • C# 数组中的 indexOf 方法及使用

    C# 数组中的 indexOf 方法及使用 在C#中,数组是一种非常常见的数据结构,它们可以用来存储多个相同类型的数据。我们可以使用indexOf方法来查找指定元素在数组中的索引位置。 indexOf 方法的语法 indexOf方法用于查找数组中指定元素的位置,语法如下: public static int indexOf(Object[] array, O…

    C# 2023年6月7日
    00
  • .NET 6新特性试用之Nuget包验证

    .NET 6 新特性试用之 Nuget 包验证攻略 Nuget 包是 .NET 开发中不可或缺的一部分,它们提供了许多有用的功能和工具,可以帮助我们更轻松地开发 .NET 应用程序。在 .NET 6 中,有一些新的 Nuget 包验证特性,可以帮助我们更好地管理和验证我们的 Nuget 包。以下是 .NET 6 新特性试用之 Nuget 包验证的完整攻略: …

    C# 2023年5月17日
    00
  • .NET Core3.0 日志 logging的实现

    在.NET Core 3.0中,日志记录(logging)是一项非常重要的任务,它可以帮助您跟踪应用程序的运行情况并诊断问题。在本攻略中,我们将详细讲解.NET Core 3.0中日志记录的实现,并提供两个示例说明。 步骤一:安装NuGet包 要使用.NET Core 3.0中的日志记录功能,您需要安装以下NuGet包: Microsoft.Extensio…

    C# 2023年5月17日
    00
  • C#的循环语句集锦及案例详解

    C#的循环语句集锦及案例详解 什么是循环语句 在编程中,循环语句是一种非常常见的语言结构,它可以让程序反复执行一定操作,直到满足特定的条件后才停止。在C#中,常用的循环语句有for循环、while循环、do-while循环和foreach循环。这些循环语句在实际编写程序中应用广泛,也是C#中比较基础的知识点。 for循环 语法 for (initializa…

    C# 2023年6月7日
    00
  • .Net 项目代码风格要求小结

    我很乐意分享一下“.Net 项目代码风格要求小结”的完整攻略。 一、标准命名规则 在 .Net 项目中,遵循标准命名规则可以提高代码的可读性和可维护性。下面是一些常用的规则: 1. 命名空间 命名空间包含一个或多个类,为了方便区分不同的模块或功能,应该使用层次结构。层次结构的命名方式应该类似于文件夹,使用点来分隔各个层级。例如: namespace Comp…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部