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日

相关文章

  • Java 8 Stream流强大的原理

    Java 8 Stream流是一个非常强大的特性,它为Java程序员提供了一个非常便捷的方式来处理集合数据。Stream流是基于Lambda表达式和函数式编程的,它是一个可以组合操作的序列化数据流。它的执行过程分为中间操作和终端操作,中间操作返回一个新的Stream流,终端操作将返回一个非Stream的结果。在这篇攻略中,我们将详细讲解Stream流的原理和…

    other 2023年6月27日
    00
  • PHP命名空间namespace定义及导入use用法详解

    PHP命名空间namespace定义及导入use用法详解 1. 什么是命名空间? 命名空间是一种将代码组织为独立且可重用的结构的技术。通过命名空间,我们可以避免命名冲突并更好地组织和管理代码。在PHP中,我们可以使用命名空间将相关的类、函数和常量组织在一起。 2. 如何定义命名空间? 使用namespace关键字可以定义一个命名空间。命名空间通常在文件的顶部…

    other 2023年6月28日
    00
  • javaweb中struts开发——bean标签

    javaweb中struts开发——bean标签 Struts是一个MVC框架,它使用JSP做Web视图,而JavaBean是作为模型的Java类。Struts使用bean标签将JavaBean绑定到表单中,处理前端与后端的信息交互,让开发更加便利。 1. bean标签 在Struts中,bean标签用于在JSP页面中创建JavaBean对象,设置属性和获取…

    其他 2023年3月28日
    00
  • 详解Mybatis核心配置文件

    下面就给您详细讲解Mybatis核心配置文件的完整攻略。 什么是Mybatis核心配置文件 Mybatis核心配置文件是Mybatis框架的重要组成部分,主要用于对数据源、缓存、事务、日志等核心功能的配置。 Mybatis核心配置文件的结构 Mybatis核心配置文件的结构如下所示: <?xml version="1.0" enco…

    other 2023年6月25日
    00
  • 微信小程序实现之手势锁功能实例代码

    gesturePath: [], // 用于记录手势路径的数组 gestureTemplate: [ // 预定义的手势模板 { x: 100, y: 100 }, { x: 200, y: 100 }, { x: 200, y: 200 }, { x: 100, y: 200 } ] }, onTouchEnd: function(event) { // …

    other 2023年7月29日
    00
  • Android编程实现应用获取包名、版本号、权限等信息的方法

    Android编程实现应用获取包名、版本号、权限等信息的方法攻略 在Android编程中,我们可以使用一些方法来获取应用的包名、版本号、权限等信息。下面是一个详细的攻略,包含了两个示例说明。 获取包名 要获取应用的包名,可以使用Context对象的getPackageName()方法。以下是获取包名的示例代码: String packageName = ge…

    other 2023年8月3日
    00
  • 人人开源之代码生成器(renren-generator)

    当然,我可以为您提供详细的“人人开源之代码生成器(renren-generator)”的完整攻略,包括两个示例说明。 人人开源之代码生成器(renren-generator)的完整攻略 renren-generator是一款基于MyBatis Plus和Spring Boot的代码生成器,可以快速生成Java后端代码。在本教程中,我们将介绍renren-ge…

    other 2023年5月7日
    00
  • 微信拍一拍新变化 微信拍一拍设置后缀方法

    微信拍一拍新变化 微信拍一拍是微信中一种用于向好友发送简短的拍打动作的功能。最近,微信进行了一些更新,使得用户可以设置拍一拍的后缀。在本攻略中,我们将详细介绍如何设置微信拍一拍的后缀。 设置微信拍一拍后缀的方法 打开微信应用并登录您的账号。 在主界面上,点击右上角的个人头像,进入个人信息页面。 在个人信息页面中,找到并点击“设置”按钮。 在设置页面中,向下滑…

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