Java多线程编程详解:从基础到高级

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

Java的多线程编程允许程序同时执行多个任务,提高了应用的性能和响应能力。本文将从基础到高级,全面介绍Java中的多线程编程,包括线程的创建、线程池、同步机制及并发工具的使用。

1. 基础线程操作

1.1 创建线程

Java中创建线程有两种主要方法:继承Thread类和实现Runnable接口。

  • 继承Thread
package cn.juwatech.example;

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

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 实现Runnable接口
package cn.juwatech.example;

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

    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

1.2 线程生命周期

线程的生命周期包括以下状态:

  • 新建:线程被创建,但尚未启动。
  • 就绪:线程被启动,等待系统分配CPU时间。
  • 运行:线程正在执行。
  • 阻塞:线程等待某些资源,如I/O操作。
  • 终止:线程执行完毕或因异常终止。

1.3 线程优先级

Java允许设置线程优先级,优先级的范围从1(最低)到10(最高):

package cn.juwatech.example;

public class ThreadPriorityExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> System.out.println("Thread 1"));
        Thread thread2 = new Thread(() -> System.out.println("Thread 2"));

        thread1.setPriority(Thread.MIN_PRIORITY); // 设置最低优先级
        thread2.setPriority(Thread.MAX_PRIORITY); // 设置最高优先级

        thread1.start();
        thread2.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

2. 线程同步

2.1 使用synchronized关键字

synchronized关键字用于保证同一时刻只有一个线程可以执行特定的代码块或方法,从而防止竞争条件:

  • 同步方法
package cn.juwatech.example;

public class SynchronizedMethod {
    private int count = 0;

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

    public static void main(String[] args) {
        SynchronizedMethod obj = new SynchronizedMethod();
        Thread t1 = new Thread(obj::increment);
        Thread t2 = new Thread(obj::increment);

        t1.start();
        t2.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 同步代码块
package cn.juwatech.example;

public class SynchronizedBlock {
    private int count = 0;

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

    public static void main(String[] args) {
        SynchronizedBlock obj = new SynchronizedBlock();
        Thread t1 = new Thread(obj::increment);
        Thread t2 = new Thread(obj::increment);

        t1.start();
        t2.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

2.2 锁机制

使用ReentrantLock类提供比synchronized更灵活的锁机制。支持尝试获取锁、定时锁和中断锁等功能:

package cn.juwatech.example;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private final Lock lock = new ReentrantLock();
    private int count = 0;

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLockExample obj = new ReentrantLockExample();
        Thread t1 = new Thread(obj::increment);
        Thread t2 = new Thread(obj::increment);

        t1.start();
        t2.start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

3. 线程池

线程池是一种线程管理机制,允许重用现有的线程,减少了线程创建和销毁的开销。Java提供了Executors类用于创建线程池。

  • 创建线程池
package cn.juwatech.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 10; i++) {
            executor.execute(() -> {
                System.out.println("Thread: " + Thread.currentThread().getName());
            });
        }

        executor.shutdown();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

4. 高级并发工具

4.1 CallableFuture

Callable接口与Runnable类似,但可以返回结果并抛出异常。Future接口用于获取任务的执行结果。

  • 使用CallableFuture
package cn.juwatech.example;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableFutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        Callable<Integer> task = () -> {
            Thread.sleep(1000);
            return 123;
        };

        Future<Integer> future = executor.submit(task);

        try {
            System.out.println("Result: " + future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        executor.shutdown();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

4.2 CountDownLatch

CountDownLatch允许一个或多个线程等待直到一组操作完成。

  • 使用CountDownLatch
package cn.juwatech.example;

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(3);

        Runnable task = () -> {
            System.out.println(Thread.currentThread().getName() + " finished");
            latch.countDown();
        };

        new Thread(task).start();
        new Thread(task).start();
        new Thread(task).start();

        try {
            latch.await();
            System.out.println("All threads have finished");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

4.3 Semaphore

Semaphore用于限制对某个资源的访问数量。

  • 使用Semaphore
package cn.juwatech.example;

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private static final Semaphore semaphore = new Semaphore(3);

    public static void main(String[] args) {
        Runnable task = () -> {
            try {
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + " acquired a permit");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + " released a permit");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        };

        for (int i = 0; i < 6; i++) {
            new Thread(task).start();
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

4.4 CyclicBarrier

CyclicBarrier允许一组线程互相等待,直到所有线程都达到某个公共屏障点。

  • 使用CyclicBarrier
package cn.juwatech.example;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        final CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("Barrier is crossed"));

        Runnable task = () -> {
            try {
                System.out.println(Thread.currentThread().getName() + " waiting at barrier");
                barrier.await();
                System.out.println(Thread.currentThread().getName() + " crossed the barrier");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        };

        new Thread(task).start();
        new Thread(task).start();
        new Thread(task).start();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.