Java多线程编程详细解释

yizhihongxing

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日

相关文章

  • ai怎么设计解决方案主题的插画? ai解决方案海报的画法

    下面是详细讲解“AI如何设计解决方案主题插画与海报画法”的攻略: 设计解决方案主题插画 步骤一:确定画面主题 首先,需要确定画面的主题,一般是与解决方案相关,表现解决方案的主要功能或特点。例如,如果是一款智能手机的解决方案,主题可以是“未来科技”。 步骤二:收集素材 收集一些在主题和主题相关领域内的素材,例如,机器人、未来城市等等,这些素材将用于画面的构成。…

    other 2023年6月26日
    00
  • ZeroMQ接口函数之 :zmq_disconnect – 断开一个socket的连接

    ZeroMQ接口函数之 :zmq_disconnect – 断开一个socket的连接 zmq_disconnect(void *socket, const char *endpoint)函数用于断开一个已建立连接的socket。这个函数的调用方式如下: int zmq_disconnect (void *socket, const char *endpoi…

    其他 2023年3月28日
    00
  • memncpy函数的用法

    当然,我很乐意为您提供有关“memncpy函数的用法”的完整攻略。以下是详细的步骤和两个示例: 1 memncpy函数的用法 memncpy函数C语言中的一个标准函数,用于将一个内存区域的内容复制到另一个内存区域。它与memcpy函数类似,是memncpy函数会在复制时限制复制的字节数,以避免内存溢出的问题。 1.1 函数原型 mem函数的原型如下: voi…

    other 2023年5月6日
    00
  • MySQL中的多字段相同数据去重复

    MySQL中的多字段相同数据去重复,可以通过使用DISTINCT关键字或者GROUP BY语句来实现。 方法一:使用DISTINCT关键字 DISTINCT关键字可用于查询不同的值。当使用DISTINCT关键字来查询表中多个字段时,只会返回那些不同的记录。例如,假设有一张名为employees的员工表,包含了员工的姓名、电子邮件和电话号码,我们希望查询所有不…

    other 2023年6月25日
    00
  • C++学习心得之扫雷游戏

    C++学习心得之扫雷游戏攻略 1. 前言 扫雷游戏是一个经典的Windows游戏,通过排除地图上的安全方块并标记地雷方块,来完成游戏。对于初学者来说,实现一个扫雷游戏是学习C++编程的好方法,因为它涉及到了C++中很多重要的概念,例如面向对象编程、游戏逻辑和图形用户界面等。 在本文中,我们将使用MFC框架来实现扫雷游戏,并介绍实现的基本思路和关键步骤。 2.…

    other 2023年6月27日
    00
  • Redis高并发防止秒杀超卖实战源码解决方案

    下面是 Redis 高并发防止秒杀超卖实战源码解决方案的攻略: 1. 需求分析 在实现秒杀的过程中,通常需要考虑如下需求: 并发访问量较高,需要使用分布式锁或 Redis 等工具来控制请求的并发数 秒杀商品数量有限,在实现过程中需要判断商品是否已经被秒杀完 同一个用户只能抢购一次,需要根据用户 ID 进行限制 2. 解决方案 针对上述需求,我们可以使用以下解…

    other 2023年6月26日
    00
  • mongodb(实现join)

    以下是关于“MongoDB(实现JOIN)”的完整攻略: MongoDB简介 MongoDB是一个开源的文档型数据库,使用JSON格式存储,支持动态查询和索引MongoDB的特点是高性能、高可用性、易扩展、灵活性高等。 MongoDB的JOIN MongoDB不支持传统SQL JOIN操作,但是可以通过一些技巧来实现类似的功能。以下是两种实现JOIN的方法:…

    other 2023年5月9日
    00
  • 探讨Java语言中那些修饰符

    探讨Java语言中的修饰符 1. 修饰符是什么? 在Java语言中,修饰符用于修饰类、方法、变量和构造方法等成员。它们可以控制访问级别,决定成员的可见性和可访问性,以及提供额外的功能和限制。Java语言中常用的修饰符有以下几种:public、private、protected、default、abstract、final、static、synchronize…

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