Java多线程编程详细解释

Java多线程编程详细解释

简介

Java中的多线程编程是一种同时执行多个线程的方式,它可以提高程序性能和资源利用率。本文将详细介绍Java多线程编程,让你能够了解创建和管理线程的方法,以及如何避免线程安全问题。

创建线程的方法

Java中有两种创建线程的方法:

方法一:继承Thread类

class MyThread extends Thread {
    public void run() {
        System.out.println("MyThread is running...");
    }
}

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

方法二:实现Runnable接口

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("MyRunnable is running...");
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    } 
}

线程状态

Java中的线程有6种状态:新建状态(New)、就绪状态(Runnable)、阻塞状态(Blocked)、等待状态(Waiting)、计时等待状态(Timed Waiting)和终止状态(Terminated)。

public class TestThreadState {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(t.getState()); // NEW
        t.start();
        System.out.println(t.getState()); // RUNNABLE
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getState()); // TIMED_WAITING
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getState()); // TERMINATED
    }
}

线程同步

多个线程之间可能会访问同一个资源,为了避免线程安全问题,我们需要对访问该资源的代码进行同步。Java中的同步机制有以下两种:

方法一: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 TestSynchronized {
    public static void main(String[] args) {
        Counter counter = new Counter();
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> counter.increment()).start();
            new Thread(() -> counter.decrement()).start();
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(counter.getCount()); // 0
    }
}

方法二: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() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

public class TestLock {
    public static void main(String[] args) {
        Counter counter = new Counter();
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> counter.increment()).start();
            new Thread(() -> counter.decrement()).start();
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(counter.getCount()); // 0
    }
}

示例一:生产者消费者问题

class Producer implements Runnable {
    private Queue<Integer> queue;
    private int max;
    public Producer(Queue<Integer> queue, int max) {
        this.queue = queue;
        this.max = max;
    }
    public void run() {
        int i = 0;
        while (true) {
            synchronized (queue) {
                while (queue.size() == max) {
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                queue.offer(i);
                System.out.println("Produced " + i);
                i++;
                queue.notifyAll();
            }
        }
    }
}

class Consumer implements Runnable {
    private Queue<Integer> queue;
    public Consumer(Queue<Integer> queue) {
        this.queue = queue;
    }
    public void run() {
        while (true) {
            synchronized (queue) {
                while (queue.isEmpty()) {
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                int num = queue.poll();
                System.out.println("Consumed " + num);
                queue.notifyAll();
            }
        }
    }
}

public class TestProducerConsumer {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        Producer p = new Producer(queue, 5);
        Consumer c = new Consumer(queue);
        new Thread(p).start();
        new Thread(c).start();
    }
}

示例二:死锁问题

public class TestDeadlock {
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lock1) {
                System.out.println("Thread 1: Holding lock 1...");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 1: Waiting for lock 2...");
                synchronized (lock2) {
                    System.out.println("Thread 1: Holding lock 1 and lock 2...");
                }
            }
        }).start();
        new Thread(() -> {
            synchronized (lock2) {
                System.out.println("Thread 2: Holding lock 2...");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Thread 2: Waiting for lock 1...");
                synchronized (lock1) {
                    System.out.println("Thread 2: Holding lock 1 and lock 2...");
                }
            }
        }).start();
    }
}

总结

Java多线程编程是Java程序的重要组成部分。通过掌握线程的基本知识,如创建和管理线程、线程状态、线程同步等,可以优化程序性能、提高资源利用率,并解决线程安全问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程编程详细解释 - Python技术站

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

相关文章

  • iQOOPad怎么进开发者模式 iQOOPad开发者模式设置方法

    下面我来详细讲解“iQOOPad怎么进开发者模式 iQOOPad开发者模式设置方法”的完整攻略。 iQOOPad进入开发者模式的方法 步骤一:打开iQOOPad的设置界面 首先,我们需要打开iQOOPad的设置界面。可以在桌面或者应用程序列表中找到“设置”图标,点击进入。 步骤二:找到“关于平板电脑”选项并点击 在设置界面中,我们需要找到“关于平板电脑”选项…

    other 2023年6月26日
    00
  • ios12 beta4有哪些bug 苹果iOS12Beta4已知bug及解决方法汇总

    iOS12 Beta4 已知 bug 总结 自从 Apple 于 6 月 4 日发布 iOS12 Beta1 开始,一直轰轰烈烈的进行着 Beta 测试。而截至目前,iOS12 Beta 已经进入到 Beta4 版本,测试内容已经非常丰富。 不过,随着 Beta 版本的不断更新,Apple 在处理问题上也越发的高效。 以下是 iOS12 Beta4 已知 b…

    other 2023年6月27日
    00
  • SpringBoot使用SchedulingConfigurer实现多个定时任务多机器部署问题(推荐)

    下面将详细讲解如何使用SchedulingConfigurer实现多个定时任务多机器部署的方法。 什么是SchedulingConfigurer SchedulingConfigurer是Spring框架中的一个接口,用于配置定时任务的线程池和任务注册中心等。通过实现该接口,我们可以自定义定时任务的配置信息。 实现多个定时任务多机器部署的步骤 下面是实现多个…

    other 2023年6月26日
    00
  • PowerShell入门教程之PowerShell有什么用?

    PowerShell入门教程之PowerShell有什么用? PowerShell是一种基于任务脚本语言的命令行Shell及其相应的脚本语言,它是Windows的内置脚本语言。与其他命令行Shell相比,PowerShell更加强大和灵活,其语法更为简化,可以用于自动化Windows系统的管理和维护。接下来,将详细讲解PowerShell的用途和功能。 Po…

    other 2023年6月27日
    00
  • Win10一周年更新14393.0已上传到Windows Update服务器(含下载地址)

    Win10一周年更新14393.0攻略 Win10一周年更新14393.0是Windows 10操作系统的一个重要更新版本。本攻略将详细介绍如何获取该更新并提供下载地址。以下是攻略的步骤: 步骤一:检查更新 首先,确保你的计算机已连接到互联网。然后按照以下步骤检查更新: 打开“设置”应用程序。你可以在开始菜单中找到它。 在“设置”窗口中,点击“更新和安全”选…

    other 2023年8月5日
    00
  • ThingJS粒子特效一键实现雨雪效果

    下面是详细的“ThingJS粒子特效一键实现雨雪效果”的攻略,包含两个示例说明: 简介 ThingJS是一个基于WebGL的3D图形库,允许用户使用JavaScript语言在网页中创建交互性的3D场景。其中的粒子系统被广泛用于创建各种特效,例如雨雪、火焰等。本文将介绍如何通过ThingJS的粒子特效库——ParticleSystem组件,实现一键雨雪效果。 …

    other 2023年6月25日
    00
  • java中array/list/map/object与json互相转换详解(转载)

    Java中Array/List/Map/Object与JSON互相转换详解(转载) 在Java中,我们常常需要进行各种类型之间的相互转换,最常见的就是把Java中的数据结构与JSON格式进行相互转换。为此,我们需要借助一些工具类库来完成,这篇文章就将详细讲解如何使用这些工具类库进行相应的转换操作。 使用Jackson库进行转换 在Java中,最常用的处理JS…

    其他 2023年3月28日
    00
  • Centos修改DNS重启或重启network服务后丢失问题解决方法

    Centos修改 DNS 重启或重启 network 服务后丢失问题解决方法 在 CentOS 上修改 DNS 后,重启或重启网络服务后可能会丢失 DNS 设置。本文将详细讲解解决方法。 问题描述 当在 CentOS 上配置 DNS 时,可能需要修改 /etc/resolv.conf 文件。然而,当重启或重启 network 服务时,这些设置会被重置为默认值…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部