📜  Java-多线程(1)

📅  最后修改于: 2023-12-03 14:42:20.277000             🧑  作者: Mango

Java 多线程

Java 是一种非常流行的面向对象编程语言,它支持多线程编程。在计算机中,多线程是指一个程序同时执行多个线程,每个线程都可以独立执行不同的任务。Java 通过 Thread 类来支持多线程编程。本文将为你介绍 Java 多线程编程的相关知识。

创建线程

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

  1. 继承 Thread
  2. 实现 Runnable 接口
继承 Thread

继承 Thread 类并重写 run 方法,然后创建该类的对象并调用 start 方法即可创建线程。示例代码如下:

class MyThread extends Thread {
    public void run() {
        System.out.println("Hello, world!");
    }
}

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

输出:

Hello, world!
实现 Runnable 接口

实现 Runnable 接口并重写 run 方法,然后创建该类的对象并作为参数传递给 Thread 类的构造方法,最后调用 start 方法即可创建线程。示例代码如下:

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Hello, world!");
    }
}

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

输出:

Hello, world!
线程同步

当多个线程共享同一个资源时,就会发生线程同步问题。Java 提供了多种方式来解决线程同步问题:

  • synchronized 方法
  • synchronized 代码块
  • volatile 关键字
  • Lock 接口
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 Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(counter.getCount());
    }
}

输出:

0
synchronized 代码块

使用 synchronized 关键字将需要同步的代码块包裹起来,也可以实现线程同步。示例代码如下:

class Counter {
    private int count = 0;

    public void increment() {
        synchronized (this) {
            count++;
        }
    }

    public void decrement() {
        synchronized (this) {
            count--;
        }
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(counter.getCount());
    }
}

输出:

0
volatile 关键字

volatile 关键字可以实现线程之间的可见性,即一个线程修改了共享变量的值,其他线程能够立即看到该变化。示例代码如下:

class Counter {
    private volatile int count = 0;

    public void increment() {
        count++;
    }

    public void decrement() {
        count--;
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(counter.getCount());
    }
}

输出:

0
Lock 接口

Lock 接口提供了更加灵活的锁定机制,可以实现更细粒度的线程同步。与 synchronized 不同,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 Main {
    public static void main(String[] args) {
        Counter counter = new Counter();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                counter.decrement();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(counter.getCount());
    }
}

输出:

0
线程池

线程池是一种提高线程利用率、减少创建线程的开销的技术。Java 中通过 ThreadPoolExecutor 类来实现线程池。示例代码如下:

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 100; i++) {
            executorService.submit(new Task(i));
        }
        executorService.shutdown();
    }
}

class Task implements Runnable {
    private int taskId;

    public Task(int taskId) {
        this.taskId = taskId;
    }

    @Override
    public void run() {
        System.out.println("Task #" + taskId + " is running.");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Task #" + taskId + " is completed.");
    }
}

输出:

Task #0 is running.
Task #1 is running.
Task #2 is running.
Task #3 is running.
Task #4 is running.
Task #5 is running.
Task #6 is running.
Task #7 is running.
Task #8 is running.
Task #9 is running.
Task #10 is running.
Task #11 is running.
Task #12 is running.
Task #13 is running.
Task #14 is running.
Task #15 is running.
Task #16 is running.
Task #17 is running.
Task #18 is running.
Task #19 is running.
Task #20 is running.
Task #21 is running.
Task #22 is running.
Task #23 is running.
Task #24 is running.
Task #25 is running.
Task #26 is running.
Task #27 is running.
Task #28 is running.
Task #29 is running.
Task #30 is running.
Task #31 is running.
Task #32 is running.
Task #33 is running.
Task #34 is running.
Task #35 is running.
Task #36 is running.
Task #37 is running.
Task #38 is running.
Task #39 is running.
Task #40 is running.
Task #41 is running.
Task #42 is running.
Task #43 is running.
Task #44 is running.
Task #45 is running.
Task #46 is running.
Task #47 is running.
Task #48 is running.
Task #49 is running.
Task #50 is running.
Task #51 is running.
Task #52 is running.
Task #53 is running.
Task #54 is running.
Task #55 is running.
Task #56 is running.
Task #57 is running.
Task #58 is running.
Task #59 is running.
Task #60 is running.
Task #61 is running.
Task #62 is running.
Task #63 is running.
Task #64 is running.
Task #65 is running.
Task #66 is running.
Task #67 is running.
Task #68 is running.
Task #69 is running.
Task #70 is running.
Task #71 is running.
Task #72 is running.
Task #73 is running.
Task #74 is running.
Task #75 is running.
Task #76 is running.
Task #77 is running.
Task #78 is running.
Task #79 is running.
Task #80 is running.
Task #81 is running.
Task #82 is running.
Task #83 is running.
Task #84 is running.
Task #85 is running.
Task #86 is running.
Task #87 is running.
Task #88 is running.
Task #89 is running.
Task #90 is running.
Task #91 is running.
Task #92 is running.
Task #93 is running.
Task #94 is running.
Task #95 is running.
Task #96 is running.
Task #97 is running.
Task #98 is running.
Task #99 is running.
Task #1 is completed.
Task #2 is completed.
Task #0 is completed.
Task #7 is completed.
Task #6 is completed.
Task #9 is completed.
Task #5 is completed.
Task #4 is completed.
Task #3 is completed.
Task #8 is completed.
Task #11 is completed.
Task #12 is completed.
Task #13 is completed.
Task #14 is completed.
Task #15 is completed.
Task #16 is completed.
Task #17 is completed.
Task #18 is completed.
Task #19 is completed.
Task #20 is completed.
Task #21 is completed.
Task #22 is completed.
Task #23 is completed.
Task #24 is completed.
Task #25 is completed.
Task #26 is completed.
Task #27 is completed.
Task #28 is completed.
Task #29 is completed.
Task #30 is completed.
Task #31 is completed.
Task #32 is completed.
Task #33 is completed.
Task #34 is completed.
Task #35 is completed.
Task #36 is completed.
Task #37 is completed.
Task #38 is completed.
Task #39 is completed.
Task #40 is completed.
Task #41 is completed.
Task #42 is completed.
Task #43 is completed.
Task #44 is completed.
Task #45 is completed.
Task #46 is completed.
Task #47 is completed.
Task #48 is completed.
Task #49 is completed.
Task #50 is completed.
Task #51 is completed.
Task #52 is completed.
Task #53 is completed.
Task #54 is completed.
Task #55 is completed.
Task #56 is completed.
Task #57 is completed.
Task #58 is completed.
Task #59 is completed.
Task #60 is completed.
Task #61 is completed.
Task #62 is completed.
Task #63 is completed.
Task #64 is completed.
Task #65 is completed.
Task #66 is completed.
Task #67 is completed.
Task #68 is completed.
Task #69 is completed.
Task #70 is completed.
Task #71 is completed.
Task #72 is completed.
Task #73 is completed.
Task #74 is completed.
Task #75 is completed.
Task #76 is completed.
Task #77 is completed.
Task #78 is completed.
Task #79 is completed.
Task #80 is completed.
Task #81 is completed.
Task #82 is completed.
Task #83 is completed.
Task #84 is completed.
Task #85 is completed.
Task #86 is completed.
Task #87 is completed.
Task #88 is completed.
Task #89 is completed.
Task #90 is completed.
Task #91 is completed.
Task #92 is completed.
Task #93 is completed.
Task #94 is completed.
Task #95 is completed.
Task #96 is completed.
Task #97 is completed.
Task #98 is completed.
Task #99 is completed.
小结

本文介绍了 Java 多线程编程的相关知识,包括创建线程、线程同步和线程池。Java 多线程编程是 Java 程序员的必备技能,希望本文能够对你有所帮助。